diff options
author | Bill Richardson <wfrichar@chromium.org> | 2014-04-16 16:10:05 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-05-15 05:20:14 +0000 |
commit | c46f569a39210c5ecc7f2f767b6a77c9554f3d73 (patch) | |
tree | 8d5544c243b4f305706e448013f31bba61588679 | |
parent | 53eb009d52fe82409784dfa6f079d45e7a2339b5 (diff) | |
download | chrome-ec-c46f569a39210c5ecc7f2f767b6a77c9554f3d73.tar.gz |
Add standalone lightbar simulation tool
This adds an "extra/" directory to hold various experiments and optional
programs. With this change, we add a tool that can simulate the lightbar
behavior on the build machine. That can be used to experment with variations
in the lightbar pattern code without needing to reflash a Pixel with a new
EC to see the effect.
There is no functional change to the EC code, just a couple of #ifdefs to
allow common/lightbar.c to be compiled separately from the EC.
BUG=none
BRANCH=ToT
TEST=make buildall -j
cd extra
make
./lightbar
You may need to install the libxcb1-dev package on your build machine.
Change-Id: I847ce7ea97cae792b1de1b91f488819e873b6555
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/199883
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | common/lightbar.c | 14 | ||||
-rw-r--r-- | extra/.gitignore | 1 | ||||
-rw-r--r-- | extra/Makefile | 20 | ||||
-rw-r--r-- | extra/README | 46 | ||||
-rw-r--r-- | extra/input.c | 46 | ||||
-rw-r--r-- | extra/main.c | 256 | ||||
-rw-r--r-- | extra/simulation.h | 108 | ||||
-rw-r--r-- | extra/windows.c | 289 | ||||
-rw-r--r-- | include/lightbar.h | 1 |
10 files changed, 781 insertions, 3 deletions
diff --git a/README b/README new file mode 100644 index 0000000000..2462fef2d5 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +For an overview of the Embedded Controller firmware, refer to + +http://www.chromium.org/chromium-os/2014-firmware-summit diff --git a/common/lightbar.c b/common/lightbar.c index 6508d897fb..82cc723555 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -6,6 +6,9 @@ * LED controls. */ +#ifdef LIGHTBAR_SIMULATION +#include "simulation.h" +#else #include "battery.h" #include "charge_state.h" #include "common.h" @@ -20,6 +23,7 @@ #include "task.h" #include "timer.h" #include "util.h" +#endif /* * The Link lightbar had no version command, so defaulted to zero. We have @@ -139,7 +143,7 @@ static void lightbar_restore_state(void) static int last_backlight_level; #endif -static int demo_mode; +static int demo_mode = DEMO_MODE_DEFAULT; /* Update the known state. */ static void get_battery_level(void) @@ -1016,7 +1020,7 @@ static void show_params(const struct lightbar_params *p) ccprintf("%d\t\t# .s0a_tick_delay (battery)\n", p->s0a_tick_delay[0]); ccprintf("%d\t\t# .s0a_tick_delay (AC)\n", p->s0a_tick_delay[1]); ccprintf("%d\t\t# .s0s3_ramp_down\n", p->s0s3_ramp_down); - ccprintf("%d\t# .s3_sleep_for\n", p->s3_sleep_for); + ccprintf("%d\t\t# .s3_sleep_for\n", p->s3_sleep_for); ccprintf("%d\t\t# .s3_ramp_up\n", p->s3_ramp_up); ccprintf("%d\t\t# .s3_ramp_down\n", p->s3_ramp_down); ccprintf("%d\t\t# .new_s0\n", p->new_s0); @@ -1032,7 +1036,7 @@ static void show_params(const struct lightbar_params *p) p->bright_bl_on_min[0], p->bright_bl_on_min[1]); ccprintf("0x%02x 0x%02x\t# .bright_bl_on_max (battery, AC)\n", p->bright_bl_on_max[0], p->bright_bl_on_max[1]); - ccprintf("%d %d %d\t\t# .battery_threshold\n", + ccprintf("%d %d %d\t# .battery_threshold\n", p->battery_threshold[0], p->battery_threshold[1], p->battery_threshold[2]); @@ -1089,6 +1093,10 @@ static int command_lightbar(int argc, char **argv) } if (!strcasecmp(argv[1], "params")) { +#ifdef LIGHTBAR_SIMULATION + if (argc > 2) + lb_read_params_from_file(argv[2], &st.p); +#endif show_params(&st.p); return EC_SUCCESS; } diff --git a/extra/.gitignore b/extra/.gitignore new file mode 100644 index 0000000000..964154302a --- /dev/null +++ b/extra/.gitignore @@ -0,0 +1 @@ +lightbar diff --git a/extra/Makefile b/extra/Makefile new file mode 100644 index 0000000000..0b6c7f7cf7 --- /dev/null +++ b/extra/Makefile @@ -0,0 +1,20 @@ +# 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. + +PROG= lightbar +HEADERS= simulation.h +SRCS= main.c windows.c input.c ../common/lightbar.c + +INCLUDE= -I. -I../include +CFLAGS= -g -Wall -Werror -pthread ${INCLUDE} -DLIGHTBAR_SIMULATION +LDFLAGS = -lX11 -lxcb -lrt + +all: ${PROG} + +${PROG} : ${SRCS} ${HEADERS} Makefile + gcc ${CFLAGS} ${SRCS} ${LDFLAGS} -o ${PROG} + +.PHONY: clean +clean: + rm -f ${PROG} diff --git a/extra/README b/extra/README new file mode 100644 index 0000000000..16659415fb --- /dev/null +++ b/extra/README @@ -0,0 +1,46 @@ + +This directory is for experiments only. It is not built automatically, +required, supported, guaranteed to work, or necessarily well-documented. + +The contents may change without warning at any time. + +------------------------------------------------------------------------------ +Lightbar simulator +------------------------------------------------------------------------------ + +Build with "make lightbar". The executable is "./lightbar". + +You may need to install libxcb1-dev or similar. + +This provides a simulation environment for the lightbar task, compiling +common/lightbar.c from the EC source, but faking the rest of the EC. + +The EC console is on stdin/stdout, delivering all input to the lightbar's +console command handler (so it prefixes any input with "lightbar"). The +lightbar itself is displayed in an X window. You can click in that window to +emulate changes to the battery level, AC connection, and brightness, all of +which are normally outside the lightbar task's direct control. + +The initial sequence is "S5". Try issuing the command "seq s3s0" to see +something more familiar. + + +Note: the Pixel lightbar circuitry has three modes of operation: + +Unpowered + + When the host CPU is off (S5/G3), all power to the lightbar and its + controller circuitry is lost. + +On + + When the host CPU is on (S0) or suspended (S3), the lightbar is powered + again. After every power loss, it will need to be reinitialized by calling + lb_init() before it can be used. + +Standby + + The lightbar controller ICs can turn off all the LED outputs to conserve + power. This is the initial state when power is applied. You can turn the + LEDs off manually by calling lb_off(). When suspended, the controller will + respond to commands, but the LEDs aren't lit. Turn them on with lb_on(). diff --git a/extra/input.c b/extra/input.c new file mode 100644 index 0000000000..dcb2a98891 --- /dev/null +++ b/extra/input.c @@ -0,0 +1,46 @@ +/* + * 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 <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "simulation.h" + +void *entry_input(void *ptr) +{ + char *got, buf[80]; + char *str, *word, *saveptr; + int argc; + char *argv[40]; + int ret; + + do { + printf("lightbar%% "); + got = fgets(buf, sizeof(buf), stdin); + if (got) { + argc = 0; + argv[argc++] = "lightbar"; + word = str = buf; + while (word && argc < ARRAY_SIZE(argv)) { + word = strtok_r(str, " \t\r\n", &saveptr); + if (word) + argv[argc++] = word; + str = 0; + } + argv[argc] = 0; + ret = fake_consolecmd_lightbar(argc, argv); + if (ret) + printf("ERROR %d\n", ret); + } + + } while (got); + + exit(0); + + return 0; +} diff --git a/extra/main.c b/extra/main.c new file mode 100644 index 0000000000..9c9e26d08d --- /dev/null +++ b/extra/main.c @@ -0,0 +1,256 @@ +/* + * 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 <pthread.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.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"); + + 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, 0, 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); +} + +timestamp_t get_time(void) +{ + timestamp_t ret = { .val = 0UL }; + 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 *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->new_s0 = val[0]; + + 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]; + } + + /* Yay */ + r = 0; +done: + if (r) + fprintf(stderr, "problem with line %d: wanted %d, got %d\n", + line, want, got); + fclose(fp); + return r; +} diff --git a/extra/simulation.h b/extra/simulation.h new file mode 100644 index 0000000000..7ec55ce0cd --- /dev/null +++ b/extra/simulation.h @@ -0,0 +1,108 @@ +/* + * 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. + */ +#ifndef _SIMULATION_H +#define _SIMULATION_H + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "lb_common.h" +#include "lightbar.h" + +/* Functions specific to our simulation environment */ +void *entry_windows(void *); +void *entry_input(void *); +void *entry_lightbar(void *); +void init_windows(void); +int lb_read_params_from_file(const char *filename, struct lightbar_params *p); +/* Interfaces to the EC code that we're encapsulating */ +void lightbar_task(void); +int fake_consolecmd_lightbar(int argc, char *argv[]); + +/* EC-specific configuration */ +#undef DEMO_MODE_DEFAULT +#define DEMO_MODE_DEFAULT 1 +#ifndef CONFIG_CONSOLE_CMDHELP +#define CONFIG_CONSOLE_CMDHELP +#endif + +/* Stuff that's too interleaved with the rest of the EC to just include */ + +/* Test an important condition at compile time, not run time */ +#define _BA1_(cond, line) \ + extern int __build_assertion_ ## line[1 - 2*!(cond)] \ + __attribute__ ((unused)) +#define _BA0_(c, x) _BA1_(c, x) +#define BUILD_ASSERT(cond) _BA0_(cond, __LINE__) + +/* Number of elements in an array */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/* Non-standard standard library functions */ +void cprintf(int zero, const char *fmt, ...); +#define ccprintf(fmt...) cprintf(0, fmt) +#define strtoi strtol + +/* Task events */ +#define TASK_EVENT_CUSTOM(x) (x & 0x0fffffff) +#define TASK_EVENT_I2C_IDLE 0x10000000 +#define TASK_EVENT_WAKE 0x20000000 +#define TASK_EVENT_MUTEX 0x40000000 +#define TASK_EVENT_TIMER 0x80000000 + +/* Time units in usecs */ +#define MSEC 1000 +#define SECOND 1000000 + +#define TASK_ID_LIGHTBAR 0 +#define CC_LIGHTBAR 0 + +/* Other definitions and structs */ +#define EC_SUCCESS 0 +#define EC_ERROR_INVAL 5 +#define EC_ERROR_PARAM1 11 +#define EC_ERROR_PARAM2 12 + +typedef int task_id_t; + +typedef union { + uint64_t val; + struct { + uint32_t lo; + uint32_t hi; + } le /* little endian words */; +} timestamp_t; + +struct host_cmd_handler_args { + const void *params; + void *response; + int response_size; +}; + +/* EC functions that we have to provide */ +uint32_t task_wait_event(int timeout_us); +uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait_for_reply); +timestamp_t get_time(void); +int system_add_jump_tag(uint16_t tag, int version, int size, const void *data); +uint8_t *system_get_jump_tag(uint16_t tag, int *version, int *size); + +/* Export unused static functions to avoid compiler warnings. */ +#define DECLARE_HOOK(X, fn, Y) \ + void fake_hook_##fn(void) { fn(); } + +#define DECLARE_HOST_COMMAND(X, fn, Y) \ + int fake_hostcmd_##fn(struct host_cmd_handler_args *args) \ + { return fn(args); } + +#define DECLARE_CONSOLE_COMMAND(X, fn, Y...) \ + int fake_consolecmd_##X(int argc, char *argv[]) \ + { return fn(argc, argv); } + +#endif /* _SIMULATION_H */ diff --git a/extra/windows.c b/extra/windows.c new file mode 100644 index 0000000000..fd09af53f5 --- /dev/null +++ b/extra/windows.c @@ -0,0 +1,289 @@ +/* + * 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 <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <xcb/xcb.h> + +#include "simulation.h" + +/*****************************************************************************/ +/* Window drawing stuff */ + +/* Dimensions - may change */ +static int win_w = 1024; +static int win_h = 32; + +static xcb_connection_t *c; +static xcb_screen_t *screen; +static xcb_drawable_t win; +static xcb_gcontext_t foreground; +static xcb_colormap_t colormap_id; + +static int lb_power; + +void init_windows(void) +{ + uint32_t mask = 0; + uint32_t values[2]; + + /* Open the connection to the X server */ + c = xcb_connect(NULL, NULL); + + /* Get the first screen */ + screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data; + + /* Get a colormap */ + colormap_id = xcb_generate_id(c); + xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, + colormap_id, screen->root, screen->root_visual); + + /* Create foreground GC */ + foreground = xcb_generate_id(c); + mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; + values[0] = screen->white_pixel; + values[1] = 0; + xcb_create_gc(c, foreground, screen->root, mask, values); + + /* Create the window */ + win = xcb_generate_id(c); + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = screen->black_pixel; + values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; + xcb_create_window(c, /* Connection */ + XCB_COPY_FROM_PARENT, /* depth */ + win, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + win_w, win_h, /* width, height */ + 10, /* border_width */ + XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ + screen->root_visual, /* visual */ + mask, values); /* masks */ + + /* Map the window on the screen */ + xcb_map_window(c, win); + + /* We flush the request */ + xcb_flush(c); +} + +void cleanup(void) +{ + xcb_destroy_window(c, win); + xcb_free_gc(c, foreground); + xcb_free_colormap(c, colormap_id); + xcb_disconnect(c); +} + +/*****************************************************************************/ +/* Draw the lightbar elements */ + +/* xcb likes 16-bit colors */ +uint16_t leds[NUM_LEDS][3] = { + {0xffff, 0x0000, 0x0000}, + {0x0000, 0xffff, 0x0000}, + {0x0000, 0x0000, 0xffff}, + {0xffff, 0xffff, 0x0000}, +}; +pthread_mutex_t leds_mutex = PTHREAD_MUTEX_INITIALIZER; + +void change_gc_color(uint16_t red, uint16_t green, uint16_t blue) +{ + uint32_t mask = 0; + uint32_t values[2]; + xcb_alloc_color_reply_t *reply; + + reply = xcb_alloc_color_reply(c, + xcb_alloc_color(c, colormap_id, + red, green, blue), + NULL); + assert(reply); + + mask = XCB_GC_FOREGROUND; + values[0] = reply->pixel; + xcb_change_gc(c, foreground, mask, values); + free(reply); +} + +void update_window(void) +{ + xcb_segment_t segments[] = { + {0, 0, win_w, win_h}, + {0, win_h, win_w, 0}, + }; + xcb_rectangle_t rect; + int w = win_w / NUM_LEDS; + int i; + uint16_t copyleds[NUM_LEDS][3]; + + if (lb_power) { + pthread_mutex_lock(&leds_mutex); + memcpy(copyleds, leds, sizeof(leds)); + pthread_mutex_unlock(&leds_mutex); + + for (i = 0; i < NUM_LEDS; i++) { + rect.x = i * w; + rect.y = 0; + rect.width = w; + rect.height = win_h; + + change_gc_color(copyleds[i][0], + copyleds[i][1], + copyleds[i][2]); + + xcb_poly_fill_rectangle(c, win, foreground, 1, &rect); + } + } else { + rect.x = 0; + rect.y = 0; + rect.width = win_w; + rect.height = win_h; + + change_gc_color(0, 0, 0); + xcb_poly_fill_rectangle(c, win, foreground, 1, &rect); + + change_gc_color(0x8080, 0, 0); + + for (i = 0; i < NUM_LEDS; i++) { + segments[0].x1 = i * w; + segments[0].y1 = 0; + segments[0].x2 = segments[0].x1 + w; + segments[0].y2 = win_h; + segments[1].x1 = segments[0].x1; + segments[1].y1 = win_h; + segments[1].x2 = segments[0].x2; + segments[1].y2 = 0; + xcb_poly_segment(c, win, foreground, 2, segments); + } + } + + xcb_flush(c); +} + +void setrgb(int led, int red, int green, int blue) +{ + led %= NUM_LEDS; + + pthread_mutex_lock(&leds_mutex); + leds[led][0] = red << 8 | red; + leds[led][1] = green << 8 | green; + leds[led][2] = blue << 8 | blue; + pthread_mutex_unlock(&leds_mutex); + + update_window(); +} + +/*****************************************************************************/ +/* lb_common stubs */ + + + +/* Brightness serves no purpose here. It's automatic on the Chromebook. */ +static int brightness = 0xc0; +void lb_set_brightness(unsigned int newval) +{ + brightness = newval; +} +uint8_t lb_get_brightness(void) +{ + return brightness; +} + +void lb_set_rgb(unsigned int led, int red, int green, int blue) +{ + int i; + if (led >= NUM_LEDS) + for (i = 0; i < NUM_LEDS; i++) + setrgb(i, red, green, blue); + else + setrgb(led, red, green, blue); +} + +int lb_get_rgb(unsigned int led, uint8_t *red, uint8_t *green, uint8_t *blue) +{ + led %= NUM_LEDS; + pthread_mutex_lock(&leds_mutex); + *red = leds[led][0]; + *green = leds[led][1]; + *blue = leds[led][2]; + pthread_mutex_unlock(&leds_mutex); + return 0; +} + +void lb_init(void) +{ + if (lb_power) + lb_set_rgb(NUM_LEDS, 0, 0, 0); +}; +void lb_off(void) +{ + lb_power = 0; + update_window(); +}; +void lb_on(void) +{ + lb_power = 1; + update_window(); +}; +void lb_start_builtin_cycle(void) { }; +void lb_hc_cmd_dump(struct ec_response_lightbar *out) +{ + printf("lightbar is %s\n", lb_power ? "on" : "off"); + memset(out, lb_power, sizeof(*out)); +}; +void lb_hc_cmd_reg(const struct ec_params_lightbar *in) { }; + + +/*****************************************************************************/ +/* Event handling stuff */ + +void *entry_windows(void *ptr) +{ + xcb_generic_event_t *e; + xcb_expose_event_t *ev; + xcb_button_press_event_t *bv; + int chg = 1; + + while ((e = xcb_wait_for_event(c))) { + + switch (e->response_type & ~0x80) { + case XCB_EXPOSE: + ev = (xcb_expose_event_t *)e; + if (win_w != ev->width || win_h != ev->height) { + win_w = ev->width; + win_h = ev->height; + } + update_window(); + break; + case XCB_BUTTON_PRESS: + bv = (xcb_button_press_event_t *)e; + switch (bv->detail) { + case 1: + demo_battery_level(-1); + break; + case 3: + demo_battery_level(+1); + break; + case 2: + chg = !chg; + demo_is_charging(chg); + break; + } + break; + } + + free(e); + } + + cleanup(); + exit(0); + return 0; +} diff --git a/include/lightbar.h b/include/lightbar.h index 4f284a43b6..0d143a2e8a 100644 --- a/include/lightbar.h +++ b/include/lightbar.h @@ -26,6 +26,7 @@ void lightbar_sequence(enum lightbar_sequence s); /* External stuff */ /* These are used for demo purposes */ +#define DEMO_MODE_DEFAULT 0 extern void demo_battery_level(int inc); extern void demo_is_charging(int ischarge); extern void demo_brightness(int inc); |