summaryrefslogtreecommitdiff
path: root/extra/lightbar/windows.c
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2014-09-10 12:33:58 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-11 20:00:21 +0000
commitdab91fe9ec6ecddea2e3f6f46d207263b58d7982 (patch)
treeaae6f9162e2498fadf2595cf92f258f9c18ddf2e /extra/lightbar/windows.c
parent0e59d4f38a97defe45351f2b1e132f76f17160e6 (diff)
downloadchrome-ec-dab91fe9ec6ecddea2e3f6f46d207263b58d7982.tar.gz
extra: Move lightbar simulator into subdirectory
This clears the top level extra directory for additional extras. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=cd extra/lightbar; make; lightbar Change-Id: If05a768e4d33cbf21b2ce47a056c960a95728558 Reviewed-on: https://chromium-review.googlesource.com/217537 Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Bill Richardson <wfrichar@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'extra/lightbar/windows.c')
-rw-r--r--extra/lightbar/windows.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/extra/lightbar/windows.c b/extra/lightbar/windows.c
new file mode 100644
index 0000000000..20b3a5780c
--- /dev/null
+++ b/extra/lightbar/windows.c
@@ -0,0 +1,294 @@
+/*
+ * 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 fake_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 (fake_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 (fake_power)
+ lb_set_rgb(NUM_LEDS, 0, 0, 0);
+};
+void lb_off(void)
+{
+ fake_power = 0;
+ update_window();
+};
+void lb_on(void)
+{
+ fake_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", fake_power ? "on" : "off");
+ memset(out, fake_power, sizeof(*out));
+};
+void lb_hc_cmd_reg(const struct ec_params_lightbar *in) { };
+
+int lb_power(int enabled)
+{
+ return fake_power;
+}
+
+
+/*****************************************************************************/
+/* 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;
+}