Files
OpenCellular/extra/windows.c
Bill Richardson 4e8751372a Make lightbar simulation compile again
This just brings the competely unsupported but occasionally useful lightbar
simulation tool up to date with the rest of the source tree so it will
compile and run again.

BUG=none
BRANCH=ToT
TEST=manual

cd extra
make
./lightbar

Change-Id: Iafeaaa5ac56a4b711c63d2c64d8c51ab4b324104
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/213206
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2014-08-20 21:07:15 +00:00

295 lines
6.3 KiB
C

/*
* 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;
}