| /* |
| * Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #include <assert.h> |
| #include <errno.h> |
| #include <inttypes.h> |
| #include <pthread.h> |
| #include <stdint.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include <time.h> |
| |
| #include "simulation.h" |
| |
| static void *(*thread_fns[])(void *) = { |
| entry_windows, |
| entry_lightbar, |
| entry_input, |
| }; |
| |
| int main(int argc, char *argv[]) |
| { |
| int i; |
| pthread_t thread[ARRAY_SIZE(thread_fns)]; |
| |
| printf("\nLook at the README file.\n"); |
| printf("Click in the window.\n"); |
| printf("Type \"help\" for commands.\n\n"); |
| fflush(stdout); |
| |
| init_windows(); |
| |
| for (i = 0; i < ARRAY_SIZE(thread_fns); i++) |
| assert(0 == pthread_create(&thread[i], NULL, thread_fns[i], 0)); |
| |
| for (i = 0; i < ARRAY_SIZE(thread_fns); i++) |
| pthread_join(thread[i], NULL); |
| |
| return 0; |
| } |
| |
| void *entry_lightbar(void *ptr) |
| { |
| lightbar_task(); |
| return 0; |
| } |
| |
| /****************************************************************************/ |
| /* Fake functions. We only have to implement enough for lightbar.c */ |
| |
| /* timespec uses nanoseconds */ |
| #define TS_USEC 1000L |
| #define TS_MSEC 1000000L |
| #define TS_SEC 1000000000L |
| |
| static void timespec_incr(struct timespec *v, time_t secs, long nsecs) |
| { |
| v->tv_sec += secs; |
| /* The nanosecond sum won't overflow, but might have a carry. */ |
| v->tv_nsec += nsecs; |
| v->tv_sec += v->tv_nsec / TS_SEC; |
| v->tv_nsec %= TS_SEC; |
| } |
| |
| |
| static pthread_mutex_t task_mutex = PTHREAD_MUTEX_INITIALIZER; |
| static pthread_cond_t task_cond = PTHREAD_COND_INITIALIZER; |
| static uint32_t task_event; |
| |
| uint32_t task_wait_event(int timeout_us) |
| { |
| struct timespec t; |
| uint32_t event; |
| |
| pthread_mutex_lock(&task_mutex); |
| |
| if (timeout_us > 0) { |
| clock_gettime(CLOCK_REALTIME, &t); |
| timespec_incr(&t, timeout_us / SECOND, timeout_us * TS_USEC); |
| |
| if (ETIMEDOUT == pthread_cond_timedwait(&task_cond, |
| &task_mutex, &t)) |
| task_event |= TASK_EVENT_TIMER; |
| } else { |
| pthread_cond_wait(&task_cond, &task_mutex); |
| } |
| |
| pthread_mutex_unlock(&task_mutex); |
| event = task_event; |
| task_event = 0; |
| return event; |
| } |
| |
| uint32_t task_set_event(task_id_t tskid, /* always LIGHTBAR */ |
| uint32_t event, |
| int wait_for_reply) /* always 0 */ |
| { |
| pthread_mutex_lock(&task_mutex); |
| task_event = event; |
| pthread_cond_signal(&task_cond); |
| pthread_mutex_unlock(&task_mutex); |
| return 0; |
| } |
| |
| |
| |
| /* Stubbed functions */ |
| |
| void cprintf(int zero, const char *fmt, ...) |
| { |
| va_list ap; |
| char *s; |
| char *newfmt = strdup(fmt); |
| |
| for (s = newfmt; *s; s++) |
| if (*s == '%' && s[1] == 'T') |
| *s = 'T'; |
| |
| va_start(ap, fmt); |
| vprintf(newfmt, ap); |
| va_end(ap); |
| |
| free(newfmt); |
| } |
| |
| void cprints(int zero, const char *fmt, ...) |
| { |
| va_list ap; |
| |
| printf("[TT "); |
| va_start(ap, fmt); |
| vprintf(fmt, ap); |
| va_end(ap); |
| printf("]\n"); |
| } |
| |
| timestamp_t get_time(void) |
| { |
| static struct timespec t_start; |
| struct timespec t; |
| timestamp_t ret; |
| |
| if (!t_start.tv_sec) |
| clock_gettime(CLOCK_REALTIME, &t_start); |
| clock_gettime(CLOCK_REALTIME, &t); |
| ret.val = (t.tv_sec - t_start.tv_sec) * SECOND + |
| (t.tv_nsec - t_start.tv_nsec) / TS_USEC; |
| return ret; |
| } |
| |
| /* We could implement these if we wanted to test their usage. */ |
| int system_add_jump_tag(uint16_t tag, int version, int size, const void *data) |
| { |
| return 0; |
| } |
| |
| uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size) |
| { |
| return 0; |
| } |
| |
| /* Copied from util/ectool.c */ |
| int lb_read_params_from_file(const char *filename, |
| struct lightbar_params_v1 *p) |
| { |
| FILE *fp; |
| char buf[80]; |
| int val[4]; |
| int r = 1; |
| int line = 0; |
| int want, got; |
| int i; |
| |
| fp = fopen(filename, "rb"); |
| if (!fp) { |
| fprintf(stderr, "Can't open %s: %s\n", |
| filename, strerror(errno)); |
| return 1; |
| } |
| |
| /* We must read the correct number of params from each line */ |
| #define READ(N) do { \ |
| line++; \ |
| want = (N); \ |
| got = -1; \ |
| if (!fgets(buf, sizeof(buf), fp)) \ |
| goto done; \ |
| got = sscanf(buf, "%i %i %i %i", \ |
| &val[0], &val[1], &val[2], &val[3]); \ |
| if (want != got) \ |
| goto done; \ |
| } while (0) |
| |
| |
| /* Do it */ |
| READ(1); p->google_ramp_up = val[0]; |
| READ(1); p->google_ramp_down = val[0]; |
| READ(1); p->s3s0_ramp_up = val[0]; |
| READ(1); p->s0_tick_delay[0] = val[0]; |
| READ(1); p->s0_tick_delay[1] = val[0]; |
| READ(1); p->s0a_tick_delay[0] = val[0]; |
| READ(1); p->s0a_tick_delay[1] = val[0]; |
| READ(1); p->s0s3_ramp_down = val[0]; |
| READ(1); p->s3_sleep_for = val[0]; |
| READ(1); p->s3_ramp_up = val[0]; |
| READ(1); p->s3_ramp_down = val[0]; |
| READ(1); p->tap_tick_delay = val[0]; |
| READ(1); p->tap_display_time = val[0]; |
| |
| READ(1); p->tap_pct_red = val[0]; |
| READ(1); p->tap_pct_green = val[0]; |
| READ(1); p->tap_seg_min_on = val[0]; |
| READ(1); p->tap_seg_max_on = val[0]; |
| READ(1); p->tap_seg_osc = val[0]; |
| READ(3); |
| p->tap_idx[0] = val[0]; |
| p->tap_idx[1] = val[1]; |
| p->tap_idx[2] = val[2]; |
| |
| READ(2); |
| p->osc_min[0] = val[0]; |
| p->osc_min[1] = val[1]; |
| READ(2); |
| p->osc_max[0] = val[0]; |
| p->osc_max[1] = val[1]; |
| READ(2); |
| p->w_ofs[0] = val[0]; |
| p->w_ofs[1] = val[1]; |
| |
| READ(2); |
| p->bright_bl_off_fixed[0] = val[0]; |
| p->bright_bl_off_fixed[1] = val[1]; |
| |
| READ(2); |
| p->bright_bl_on_min[0] = val[0]; |
| p->bright_bl_on_min[1] = val[1]; |
| |
| READ(2); |
| p->bright_bl_on_max[0] = val[0]; |
| p->bright_bl_on_max[1] = val[1]; |
| |
| READ(3); |
| p->battery_threshold[0] = val[0]; |
| p->battery_threshold[1] = val[1]; |
| p->battery_threshold[2] = val[2]; |
| |
| READ(4); |
| p->s0_idx[0][0] = val[0]; |
| p->s0_idx[0][1] = val[1]; |
| p->s0_idx[0][2] = val[2]; |
| p->s0_idx[0][3] = val[3]; |
| |
| READ(4); |
| p->s0_idx[1][0] = val[0]; |
| p->s0_idx[1][1] = val[1]; |
| p->s0_idx[1][2] = val[2]; |
| p->s0_idx[1][3] = val[3]; |
| |
| READ(4); |
| p->s3_idx[0][0] = val[0]; |
| p->s3_idx[0][1] = val[1]; |
| p->s3_idx[0][2] = val[2]; |
| p->s3_idx[0][3] = val[3]; |
| |
| READ(4); |
| p->s3_idx[1][0] = val[0]; |
| p->s3_idx[1][1] = val[1]; |
| p->s3_idx[1][2] = val[2]; |
| p->s3_idx[1][3] = val[3]; |
| |
| for (i = 0; i < ARRAY_SIZE(p->color); i++) { |
| READ(3); |
| p->color[i].r = val[0]; |
| p->color[i].g = val[1]; |
| p->color[i].b = val[2]; |
| } |
| |
| #undef READ |
| |
| /* Yay */ |
| r = 0; |
| done: |
| if (r) |
| fprintf(stderr, "problem with line %d: wanted %d, got %d\n", |
| line, want, got); |
| fclose(fp); |
| return r; |
| } |