int core_init (actuator_t *act) { char buf[256]; FILE *proc; unsigned int affinity; snprintf(buf, sizeof(buf), "taskset -p %d | sed 's/.* //'", (int)act->pid); proc = popen(buf, "r"); fail_if(!proc, "cannot read initial processor affinity"); fail_if(fscanf(proc, "%x", &affinity) < 1, "cannot parse initial processor affinity"); pclose(proc); act->value = 0; while (affinity) { act->value += affinity & 0x01; affinity /= 2; } act->set_value = act->value; act->min = 1; act->max = get_core_count(); return 0; fail: return -1; }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); for (i = 0; i < ncores; i++) set_cpu_possible(i, true); }
void smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); for (i = 0; i < ncores; i++) cpu_set(i, cpu_possible_map); }
void __init platform_smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned long addr; int i; edb_trace(1); edb_putstr("smp_prepare_cpus\n"); /* sanity check */ if (ncores == 0) { printk(KERN_ERR "hisik3: strange CM count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "hisik3: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } /* * are we trying to boot more cores than exist? */ if (max_cpus > ncores) { WARN(1, "hisik3: smp max cpus should NOT more cores than exist\n"); max_cpus = ncores; } /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); scu_enable(scu_base_addr()); addr = (unsigned long) IO_ADDRESS(MEMORY_AXI_SECOND_CPU_BOOT_ADDR); printk("poke_milo addr 0x%lx at 0x%x\n", addr, virt_to_phys(k3v2_secondary_startup)); /* * Write the address of secondary startup into the system-wide flags * register. The BootMonitor waits for this register to become * non-zero. */ writel(BSYM(virt_to_phys(k3v2_secondary_startup)), addr); wmb(); flush_cache_all(); edb_putstr("smp_prepare_cpus out\n"); }
void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned int cpu = smp_processor_id(); int i; /* sanity check */ if (ncores == 0) { printk(KERN_ERR "Realview: strange CM count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "Realview: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } smp_store_cpu_info(cpu); /* * are we trying to boot more cores than exist? */ if (max_cpus > ncores) max_cpus = ncores; #ifdef CONFIG_LOCAL_TIMERS /* * Enable the local timer for primary CPU. If the device is * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in * realview_timer_init */ local_timer_setup(); #endif /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ for (i = 0; i < max_cpus; i++) cpu_set(i, cpu_present_map); /* * Initialise the SCU if there are more than one CPU and let * them know where to start. Note that, on modern versions of * MILO, the "poke" doesn't actually do anything until each * individual core is sent a soft interrupt to get it out of * WFI */ if (max_cpus > 1) { scu_enable(); poke_milo(); } }
void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); for (i = 0; i < ncores; i++) cpu_set(i, cpu_possible_map); set_smp_cross_call(gic_raise_softirq); }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init brcm_smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); for (i = 0; i < ncores; i++) set_cpu_possible(i, true); // set_smp_cross_call(gic_raise_softirq); }
static void test_get_core_count(void) { int32_t rtrn = 0; uint32_t count = 0; rtrn = get_core_count(&count); TEST_ASSERT(rtrn == 0); TEST_ASSERT(count > 0); /* A second call should have the same result. */ uint32_t second_count = 0; rtrn = get_core_count(&second_count); TEST_ASSERT(rtrn == 0); TEST_ASSERT(second_count > 0); TEST_ASSERT(count == second_count); return; }
void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned int cpu = smp_processor_id(); int i; /* sanity check */ if (ncores == 0) { printk(KERN_ERR "Realview: strange CM count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "Realview: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } smp_store_cpu_info(cpu); /* * are we trying to boot more cores than exist? */ if (max_cpus > ncores) max_cpus = ncores; /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); /* * Initialise the SCU if there are more than one CPU and let * them know where to start. Note that, on modern versions of * MILO, the "poke" doesn't actually do anything until each * individual core is sent a soft interrupt to get it out of * WFI */ if (max_cpus > 1) { /* * Enable the local timer or broadcast device for the * boot CPU, but only if we have more than one CPU. */ percpu_timer_setup(); scu_enable(scu_base_addr()); poke_milo(); } }
int machine_speed_init (actuator_t *act) { machine_state_data_t *data; unsigned long *states, *all_states; unsigned long *in_state, *out_state; int state_count, filtered_count; int core_count, i; freq_scaler_data_t *freq_data; act->data = data = malloc(sizeof(machine_state_data_t)); fail_if(!data, "cannot allocate powerstate data block"); get_actuators(&data->core_act, NULL, 16, &data->freq_acts[0], NULL); fail_if(data->core_act->max > 16, "too many cores lol"); freq_data = data->freq_acts[0]->data; core_count = get_core_count(); all_states = create_machine_states(&state_count, core_count, freq_data->freq_count, freq_data->freq_array); fail_if(!all_states, "cannot generate machine states"); qsort(all_states, state_count, STATE_SIZE(core_count), compare_states_on_speed); states = malloc(STATE_SIZE(core_count) * state_count); for (i = 0, in_state = all_states, out_state = states, filtered_count = 0; i < state_count; i++, in_state+=STATE_LEN(core_count)) { if (!redundant_state(in_state, core_count) && !drop_equivalent(in_state, i, all_states, state_count, core_count) && pareto_optimal(in_state, i, all_states, state_count, core_count) && in_state[SPEED_IDX] > 0) { #if DEBUG int j; printf("%lu\t%lu", in_state[SPEED_IDX], in_state[POWER_IDX]); for (j = 0; j < core_count; j++) printf("\t%lu", in_state[CORE_IDX(j)]); printf("\n"); #endif memmove (out_state, in_state, STATE_SIZE(core_count)); out_state += STATE_LEN(core_count); filtered_count++; } } data->state_count = state_count = filtered_count; data->states = states = realloc(states, STATE_SIZE(core_count) * state_count); free(all_states); act->min = STATE_I(states, core_count, 0)[SPEED_IDX]; act->max = STATE_I(states, core_count, state_count-1)[SPEED_IDX]; data->scratch_state = malloc(STATE_SIZE(core_count)); act->value = act->set_value = get_current_speed(act); return 0; fail: return -1; }
int global_freq_act (actuator_t *act) { int err = 0; int cpu; for (cpu = 0; cpu < get_core_count(); cpu++) err = err || cpufreq_set_frequency(cpu, act->set_value); /* warning: cpufreq_set_frequency tries sysfs first, then proc; this means that if sysfs fails with EACCESS, the errno is then masked by the ENOENT from proc! */ act->value = cpufreq_get_freq_kernel(0); return err; }
void __init smp_init_cpus(void) { unsigned i; unsigned int ncpus = get_core_count(); unsigned int core_id = get_core_id(); pr_info("%s: Core Count = %d\n", __func__, ncpus); pr_info("%s: Core Id = %d\n", __func__, core_id); for (i = 0; i < ncpus; ++i) set_cpu_possible(i, true); }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { unsigned int i, ncores; /* Never released */ scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); BUG_ON(!scu_base); ncores = get_core_count(); for (i = 0; i < ncores; i++) set_cpu_possible(i, true); }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init msm_smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", ncores, nr_cpu_ids); ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); }
void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned int cpu = smp_processor_id(); int i; /* sanity check */ if (ncores == 0) { printk(KERN_ERR "Realview: strange CM count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "Realview: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } smp_store_cpu_info(cpu); /* * are we trying to boot more cores than exist? */ if (max_cpus > ncores) max_cpus = ncores; /* * Enable the local timer for primary CPU */ local_timer_setup(cpu); /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ for (i = 0; i < max_cpus; i++) cpu_set(i, cpu_present_map); /* * Do we need any more CPUs? If so, then let them know where * to start. Note that, on modern versions of MILO, the "poke" * doesn't actually do anything until each individual core is * sent a soft interrupt to get it out of WFI */ if (max_cpus > 1) poke_milo(); }
void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned int ncores = get_core_count(); unsigned int cpu = smp_processor_id(); int i; /* sanity check */ if (ncores == 0) { printk(KERN_ERR "OMAP4: strange core count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "OMAP4: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } smp_store_cpu_info(cpu); /* * are we trying to boot more cores than exist? */ if (max_cpus > ncores) max_cpus = ncores; /* * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ for (i = 0; i < max_cpus; i++) set_cpu_present(i, true); if (max_cpus > 1) { /* * Enable the local timer or broadcast device for the * boot CPU, but only if we have more than one CPU. */ percpu_timer_setup(); /* * Initialise the SCU and wake up the secondary core using * wakeup_secondary(). */ scu_enable(scu_base); wakeup_secondary(); } }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); if (ncores > nr_cpu_ids) { pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", ncores, nr_cpu_ids); ncores = nr_cpu_ids; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); set_smp_cross_call(gic_raise_softirq); }
void __init smp_init_cpus(void) { unsigned i; unsigned int ncpus = get_core_count(); unsigned int core_id = get_core_id(); pr_info("%s: Core Count = %d\n", __func__, ncpus); pr_info("%s: Core Id = %d\n", __func__, core_id); if (ncpus > NR_CPUS) { ncpus = NR_CPUS; pr_info("%s: limiting core count by %d\n", __func__, ncpus); } for (i = 0; i < ncpus; ++i) set_cpu_possible(i, true); }
static int __cpuinit release_secondary(unsigned int cpu) { BUG_ON(cpu >= get_core_count()); if (cpu_is_msm8x60()) return scorpion_release_secondary(); if (machine_is_msm8960_sim() || machine_is_msm8960_rumi3() || machine_is_apq8064_sim()) return krait_release_secondary_sim(cpu); if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) return krait_release_secondary(cpu); WARN(1, "unknown CPU case in release_secondary\n"); return -EINVAL; }
unsigned long get_current_speed(actuator_t *act) { machine_state_data_t *data = act->data; unsigned long *current_state = data->scratch_state; int i, core_count = get_core_count(); for (i = 0; i < core_count; i++) current_state[CORE_IDX(i)] = i < data->core_act->value ? data->freq_acts[i]->value : 0; calculate_state_properties(current_state, core_count); #if DEBUG int j; printf("%lu\t%lu", current_state[SPEED_IDX], current_state[POWER_IDX]); for (j = 0; j < core_count; j++) printf("\t%lu", current_state[CORE_IDX(j)]); printf("\n"); #endif return current_state[SPEED_IDX]; }
static int release_secondary(unsigned int cpu) { BUG_ON(cpu >= get_core_count()); if (cpu_is_msm8x60()) return scorpion_release_secondary(); if (machine_is_msm8974_sim()) return krait_release_secondary_sim(0xf9088000, cpu); if (soc_class_is_msm8960() || soc_class_is_msm8930() || soc_class_is_apq8064()) return krait_release_secondary(0x02088000, cpu); if (cpu_is_msm8974()) return krait_release_secondary_p3(0xf9088000, cpu); WARN(1, "unknown CPU case in release_secondary\n"); return -EINVAL; }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); edb_putstr("smp_init_cpus\n"); /* sanity check */ if (ncores > NR_CPUS) { printk(KERN_WARNING "hisik3: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); set_smp_cross_call(gic_raise_softirq); }
/* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ void __init smp_init_cpus(void) { unsigned int i, ncores = get_core_count(); /* sanity check */ if (ncores == 0) { printk(KERN_ERR "OX820: strange CM count of 0? Default to 1\n"); ncores = 1; } if (ncores > NR_CPUS) { printk(KERN_WARNING "OX820: no. of cores (%d) greater than configured " "maximum of %d - clipping\n", ncores, NR_CPUS); ncores = NR_CPUS; } for (i = 0; i < ncores; i++) set_cpu_possible(i, true); set_smp_cross_call(gic_raise_softirq); }
int main(int argc, char **argv) { struct cpufreq_available_frequencies *freq_list; int core_count; int i, j; unsigned long *states, *state; int state_count; int opt; int skip_redundant = 0; int skip_unoptimal = 0; char *state_file_name = NULL; int skip_equivalent = 0; while ((opt = getopt(argc, argv, "rpf:u")) != -1) switch (opt) { case 'r': skip_redundant = 1; break; case 'p': skip_unoptimal = 1; break; case 'f': state_file_name = optarg; break; case 'u': skip_equivalent = 1; break; default: fprintf(stderr, "Usage: %s [-r] [-p] [-f file] [-u]\n", argv[0]); exit(1); } if (state_file_name) { states = read_states_file(state_file_name, &state_count, &core_count); } else { int freq_count; unsigned long *freq_array; core_count = get_core_count(); freq_list = cpufreq_get_available_frequencies(0); freq_count = create_freq_array(freq_list, &freq_array); states = create_machine_states(&state_count, core_count, freq_count, freq_array); } qsort(states, state_count, STATE_SIZE(core_count), compare_states_on_speed); printf("speed\tpower"); for (j = 0; j < core_count; j++) printf("\tcore%d", j); printf("\n"); for (i = 0, state = states; i < state_count; i++, state+=STATE_LEN(core_count)) { if (skip_redundant && redundant_state(state, core_count)) continue; if (skip_equivalent && drop_equivalent(state, i, states, state_count, core_count)) continue; if (skip_unoptimal && !pareto_optimal(state, i, states, state_count, core_count)) continue; printf("%lu\t%lu", state[SPEED_IDX], state[POWER_IDX]); for (j = 0; j < core_count; j++) printf("\t%lu", state[CORE_IDX(j)]); printf("\n"); } return 0; }
int main(int argc, char **argv) { int n_apps = 0; int apps[16]; int err; int i; int64_t window_size; int64_t skip_until_beat = 0; int64_t last_beat = 0; heartbeat_record_t current; int core_count; int opt; int max_beats = INT_MAX; extern int actuator_count; extern actuator_t *controls; actuator_t *next_ctl; decision_function_t decision_f = machine_state_controller; int acted; /* we want to see this in realtime even when it's piped through tee */ setlinebuf(stdout); /* getting rich with stock options */ while ((opt = getopt(argc, argv, "d:")) != -1) switch (opt) { case 'd': if (strcmp(optarg, "core_heuristics") == 0) decision_f = core_heuristics; else if (strcmp(optarg, "freq_heuristics") == 0) decision_f = freq_heuristics; else if (strcmp(optarg, "uncoordinated_heuristics") == 0) decision_f = uncoordinated_heuristics; else if (strcmp(optarg, "step_heuristics") == 0) decision_f = step_heuristics; else if (strcmp(optarg, "core_controller") == 0) decision_f = core_controller; else if (strcmp(optarg, "machine_state_controller") == 0) decision_f = machine_state_controller; else { fprintf(stderr, "%s: unknown decision function\n", argv[0]); exit(1); } break; default: fprintf(stderr, "Usage: %s [-d decision_function]\n", argv[0]); exit(1); } argc -= optind; argv += optind; if (argc > 1) max_beats = argv[1]; /* setupping arbit */ heartbeat_dir = getenv("HEARTBEAT_ENABLED_DIR"); fail_if(heartbeat_dir == NULL, "environment variable HEARTBEAT_ENABLED_DIR undefined"); while (n_apps == 0) n_apps = get_heartbeat_apps(apps, sizeof(apps)/sizeof(apps[0])); fail_if(n_apps != 1, "this service only supports a single app. please delete c:\\system32"); printf("monitoring process %d\n", apps[0]); /* initrogenizing old river control structure */ core_count = get_core_count(); actuator_count = core_count + 3; controls = malloc(sizeof(actuator_t) * actuator_count); fail_if(!controls, "could not allocate actuators"); /* PROBLEM!!!!! the machine speed actuator needs to init last, but act first! WHAT NOW */ /* create the list in action order, but init in special order... QUICK AND DIRTY = OPTIMAL */ next_ctl = controls; *next_ctl++ = (actuator_t) { .id = ACTUATOR_MACHINE_SPD, .core = -1, .pid = apps[0], .init_f = machine_speed_init, .action_f = machine_speed_act }; for (i = 0; i < core_count; i++) *next_ctl++ = (actuator_t) { .id = ACTUATOR_SINGLE_FREQ, .core = i, .pid = -1, .init_f = single_freq_init, .action_f = single_freq_act }; *next_ctl++ = (actuator_t) { .id = ACTUATOR_GLOBAL_FREQ, .core = -1, .pid = -1, .init_f = global_freq_init, .action_f = global_freq_act }; *next_ctl++ = (actuator_t) { .id = ACTUATOR_CORE_COUNT, .core = -1, .pid = apps[0], .init_f = core_init, .action_f = core_act }; for (i = 1; i < actuator_count; i++) { err = controls[i].init_f(&controls[i]); fail_if(err, "cannot initialize actuator"); } /* initialize machine speed actuator last! */ err = controls[0].init_f(&controls[0]); fail_if(err, "cannot initialize actuator"); /* begin monitoration of lone protoss */ err = heart_rate_monitor_init(&hrm, apps[0]); fail_if(err, "cannot start heart rate monitor"); window_size = hrm_get_window_size(&hrm); current.beat = -1; do { do { err = hrm_get_current(&hrm, ¤t); } while (err || current.beat <= last_beat || current.window_rate == 0.0); last_beat = current.beat; if (current.beat < skip_until_beat) { print_status(¤t, skip_until_beat, '.', actuator_count, controls); continue; } /*printf("Current beat: %lld, tag: %d, window: %lld, window_rate: %f\n", current.beat, current.tag, window_size, current.window_rate);*/ decision_f(¤t, actuator_count, controls); acted = 0; for (i = 0; i < actuator_count; i++) { actuator_t *act = &controls[i]; if (act->set_value != act->value) { #if DEBUG printf("act %d: %d -> %d\n", i, act->value, act->set_value); #endif err = act->action_f(act); /* TODO: handle error */ if (err) fprintf(stderr, "action %d failed: %s\n", act->id, strerror(errno)); acted = 1; } } /* this is horrible but necessary */ controls[0].value = get_current_speed(&controls[0]); skip_until_beat = current.beat + (acted ? window_size : 1); print_status(¤t, skip_until_beat, acted ? '*' : '=', actuator_count, controls); } while (current.beat < max_beats); heart_rate_monitor_finish(&hrm); return 0; fail: return 1; } /* here are some globals without lexical scoping, just to mix things up! */ int actuator_count; actuator_t *controls;
static int create_type9(RECORD **anrecord, struct finger_view_minutiae_record *fvmr, unsigned int idc) { FIELD *field = NULL; SUBFIELD *subfield = NULL; ITEM *item = NULL; RECORD *lrecord; // For local convenience struct finger_minutiae_data **fmds = NULL; struct ridge_count_data **rcds = NULL; struct core_data **cds; struct delta_data **dds; char buf[16]; int mincnt, minidx, rdgcnt; int cnt, i; unsigned int x, y; if (new_ANSI_NIST_record(anrecord, TYPE_9_ID) != 0) ALLOC_ERR_EXIT("Type-9 Record"); lrecord = *anrecord; /*** 9.001 - Length ***/ // Set to 0 now, will recalculate later APPEND_TYPE9_FIELD(lrecord, LEN_ID, "0"); /*** 9.002 - IDC value ***/ snprintf(buf, sizeof(buf), IDC_FMT, idc); APPEND_TYPE9_FIELD(lrecord, IDC_ID, buf); /*** 9.003 - Impression type ***/ CRW(fvmr->impression_type, MIN_TABLE_5_CODE, MAX_TABLE_5_CODE, "Impression type"); snprintf(buf, sizeof(buf), "%d", fvmr->impression_type); APPEND_TYPE9_FIELD(lrecord, IMP_ID, buf); /*** 9.004 - Minutiae format ***/ APPEND_TYPE9_FIELD(lrecord, FMT_ID, STD_STR); /*** 9.005 - Originating fingerprint reading system ***/ if (value2subfield(&subfield, "EXISTING IMAGE") != 0) ERR_OUT("creating Type-9 subfield"); if (value2item(&item, AUTO_STR) != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); if (new_ANSI_NIST_field(&field, TYPE_9_ID, OFR_ID) != 0) ERR_OUT("creating Type-9 field"); if (append_ANSI_NIST_field(field, subfield) != 0) ERR_OUT("appending Type-9 subfield"); if (append_ANSI_NIST_record(lrecord, field) != 0) ERR_OUT("appending Type-9 field"); /*** 9.006 - Finger position ***/ snprintf(buf, sizeof(buf), "%02d", fvmr->finger_number); APPEND_TYPE9_FIELD(lrecord, FGP2_ID, buf); /*** 9.007 - Fingerprint pattern classification ***/ if (value2subfield(&subfield, TBL_STR) != 0) ERR_OUT("creating Type-9 subfield"); if (value2item(&item, "UN") != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); if (new_ANSI_NIST_field(&field, TYPE_9_ID, FPC_ID) != 0) ERR_OUT("creating Type-9 field"); if (append_ANSI_NIST_field(field, subfield) != 0) ERR_OUT("appending Type-9 subfield"); if (append_ANSI_NIST_record(lrecord, field) != 0) ERR_OUT("appending Type-9 field"); /*** 9.008 - Core position ***/ cnt = get_core_count(fvmr); if (cnt > 0) { if (new_ANSI_NIST_field(&field, TYPE_9_ID, CRP_ID) != 0) ERR_OUT("allocating field"); cds = (struct core_data **) malloc( cnt * sizeof(struct core_data **)); if (cds == NULL) ALLOC_ERR_EXIT("Core data"); if (get_cores(fvmr, cds) != cnt) ERR_OUT("retrieving core data"); for (i = 0; i < cnt; i++) { convert_xy(fvmr->fmr->x_image_size, fvmr->fmr->y_image_size, fvmr->fmr->x_resolution, fvmr->fmr->y_resolution, cds[i]->x_coord, cds[i]->y_coord, &x, &y); snprintf(buf, sizeof(buf), "%04u%04u", x, y); if (value2subfield(&subfield, buf) != 0) ERR_OUT("creating subfield"); if (append_ANSI_NIST_field(field, subfield) != 0) ERR_OUT("appending subfield"); } if (append_ANSI_NIST_record(lrecord, field) != 0) ERR_OUT("adding field to record"); } else if (cnt < 0) ERR_OUT("getting core record count"); /*** 9.009 - Delta(s) position ***/ cnt = get_delta_count(fvmr); if (cnt > 0) { if (new_ANSI_NIST_field(&field, TYPE_9_ID, DLT_ID) != 0) ERR_OUT("creating Type-9 field"); dds = (struct delta_data **) malloc( cnt * sizeof(struct delta_data **)); if (dds == NULL) ALLOC_ERR_EXIT("Delta data"); if (get_deltas(fvmr, dds) != cnt) ERR_OUT("retrieving delta data"); for (i = 0; i < cnt; i++) { convert_xy(fvmr->fmr->x_image_size, fvmr->fmr->y_image_size, fvmr->fmr->x_resolution, fvmr->fmr->y_resolution, dds[i]->x_coord, dds[i]->y_coord, &x, &y); snprintf(buf, sizeof(buf), "%04u%04u", x, y); if (value2subfield(&subfield, buf) != 0) ERR_OUT("creating subfield"); if (append_ANSI_NIST_field(field, subfield) != 0) ERR_OUT("appending subfield"); } if (append_ANSI_NIST_record(lrecord, field) != 0) ERR_OUT("adding field to record"); } else if (cnt < 0) ERR_OUT("getting delta record count"); /*** 9.010 - Number of minutiae ***/ mincnt = get_fmd_count(fvmr); if (mincnt < 0) ERR_OUT("getting minutiae count"); snprintf(buf, sizeof(buf), "%d", mincnt); APPEND_TYPE9_FIELD(lrecord, MIN_ID, buf); /*** 9.011 - Minutiae ridge count indicator ***/ rdgcnt = get_rcd_count(fvmr); if (rdgcnt > 0) { rcds = (struct ridge_count_data **) malloc( rdgcnt * sizeof(struct ridge_count_data **)); if (rcds == NULL) ALLOC_ERR_EXIT("Ridge Count data"); if (get_rcds(fvmr, rcds) != rdgcnt) ERR_OUT("retrieving ridge count data"); APPEND_TYPE9_FIELD(lrecord, RDG_ID, "1"); } else if (rdgcnt < 0) ERR_OUT("getting ridge record count"); else APPEND_TYPE9_FIELD(lrecord, RDG_ID, "0"); /*** 9.012 - Minutiae and ridge count data ***/ fmds = (struct finger_minutiae_data **) malloc( mincnt * sizeof(struct finger_minutiae_data **)); if (fmds == NULL) ALLOC_ERR_EXIT("Finger Minutiae data"); if (get_fmds(fvmr, fmds) != mincnt) ERR_OUT("retrieving minutiae data"); if (new_ANSI_NIST_field(&field, TYPE_9_ID, MRC_ID) != 0) ERR_OUT("creating Type-9 field"); for (minidx = 0; minidx < mincnt; minidx++) { unsigned int theta, rdgidx, minqual; char mintype; int idxnum = minidx + 1; // Index number snprintf(buf, sizeof(buf), "%03d", idxnum); if (value2subfield(&subfield, buf) != 0) ERR_OUT("creating Type-9 subfield"); // X, Y, and theta values convert_xy(fvmr->fmr->x_image_size, fvmr->fmr->y_image_size, fvmr->fmr->x_resolution, fvmr->fmr->y_resolution, fmds[minidx]->x_coord, fmds[minidx]->y_coord, &x, &y); convert_theta(fmds[minidx]->angle, &theta); snprintf(buf, sizeof(buf), "%04u%04u%03u", x, y, theta); if (value2item(&item, buf) != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); // Quality measure convert_quality(fmds[minidx]->quality, &minqual); snprintf(buf, sizeof(buf), "%u", minqual); if (value2item(&item, buf) != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); // Minutia type designation convert_type(fmds[minidx]->type, &mintype); snprintf(buf, sizeof(buf), "%c", mintype); if (value2item(&item, buf) != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); // Ridge count data: If the one of the index numbers // in the record matches the minutia index, then add that // ridge count data to the Type-9 record, using the index // number that is the 'other'. for (rdgidx = 0; rdgidx < rdgcnt; rdgidx++) { if ((rcds[rdgidx]->index_one == idxnum) || (rcds[rdgidx]->index_two == idxnum)) { snprintf(buf, sizeof(buf), "%u,%u", (rcds[rdgidx]->index_one == idxnum) ? rcds[rdgidx]->index_two : rcds[rdgidx]->index_one, rcds[rdgidx]->count); if (value2item(&item, buf) != 0) ERR_OUT("creating Type-9 item"); if (append_ANSI_NIST_subfield(subfield, item) != 0) ERR_OUT("appending Type-9 item"); } } if (append_ANSI_NIST_field(field, subfield) != 0) ERR_OUT("appending Type-9 subfield"); } free(fmds); if (append_ANSI_NIST_record(lrecord, field) != 0) ERR_OUT("appending Type-9 field"); /*** End of minutiae and ridge count */ // Calculate and update the record length field if (update_ANSI_NIST_tagged_record_LEN(lrecord) != 0) ERR_OUT("updating Type-9 record length"); return 0; err_out: fprintf(stderr, "Error creating Type-9 record\n"); if (item != NULL) free_ANSI_NIST_item(item); if (subfield != NULL) free_ANSI_NIST_subfield(subfield); if (field != NULL) free_ANSI_NIST_field(field); if (lrecord != NULL) free_ANSI_NIST_record(lrecord); if (fmds != NULL) free(fmds); return -1; }