Files
OpenCellular/extra/lightbar/windows.c
Vic Yang 91cfdd0dac Remove PULSE and TEST sequences from lightbar module
PULSE and TEST sequences are not used anywhere. Remove them to save
flash space. Also, fix msleep(MSEC) calls in the unit test; it's
essentially usleep(SECOND) written in an incorrect way.

BUG=chrome-os-partner:32203
TEST=make buildall
BRANCH=None

Change-Id: I61ba897df632538eb89364a4c913d5fee87f3864
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/220711
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
2014-10-08 02:50:54 +00:00

294 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_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;
}