Pebble: Support taking Pebble Time screenshots. Closes #97.

This commit is contained in:
Andreas Shimokawa 2015-08-22 00:14:14 +02:00
parent 12337836bc
commit 1150ad2b8d
2 changed files with 114 additions and 19 deletions

View File

@ -202,6 +202,97 @@ public class PebbleProtocol extends GBDeviceProtocol {
GBDeviceEventScreenshot mDevEventScreenshot = null;
int mScreenshotRemaining = -1;
//monochrome black + white
static final byte[] clut_pebble = {
0x00, 0x00, 0x00, 0x00,
(byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00
};
// linear BGR222 (6 bit, 64 entries)
static final byte[] clut_pebbletime = new byte[]{
0x00, 0x00, 0x00, 0x00,
0x55, 0x00, 0x00, 0x00,
(byte) 0xaa, 0x00, 0x00, 0x00,
(byte) 0xff, 0x00, 0x00, 0x00,
0x00, 0x55, 0x00, 0x00,
0x55, 0x55, 0x00, 0x00,
(byte) 0xaa, 0x55, 0x00, 0x00,
(byte) 0xff, 0x55, 0x00, 0x00,
0x00, (byte) 0xaa, 0x00, 0x00,
0x55, (byte) 0xaa, 0x00, 0x00,
(byte) 0xaa, (byte) 0xaa, 0x00, 0x00,
(byte) 0xff, (byte) 0xaa, 0x00, 0x00,
0x00, (byte) 0xff, 0x00, 0x00,
0x55, (byte) 0xff, 0x00, 0x00,
(byte) 0xaa, (byte) 0xff, 0x00, 0x00,
(byte) 0xff, (byte) 0xff, 0x00, 0x00,
0x00, 0x00, 0x55, 0x00,
0x55, 0x00, 0x55, 0x00,
(byte) 0xaa, 0x00, 0x55, 0x00,
(byte) 0xff, 0x00, 0x55, 0x00,
0x00, 0x55, 0x55, 0x00,
0x55, 0x55, 0x55, 0x00,
(byte) 0xaa, 0x55, 0x55, 0x00,
(byte) 0xff, 0x55, 0x55, 0x00,
0x00, (byte) 0xaa, 0x55, 0x00,
0x55, (byte) 0xaa, 0x55, 0x00,
(byte) 0xaa, (byte) 0xaa, 0x55, 0x00,
(byte) 0xff, (byte) 0xaa, 0x55, 0x00,
0x00, (byte) 0xff, 0x55, 0x00,
0x55, (byte) 0xff, 0x55, 0x00,
(byte) 0xaa, (byte) 0xff, 0x55, 0x00,
(byte) 0xff, (byte) 0xff, 0x55, 0x00,
0x00, 0x00, (byte) 0xaa, 0x00,
0x55, 0x00, (byte) 0xaa, 0x00,
(byte) 0xaa, 0x00, (byte) 0xaa, 0x00,
(byte) 0xff, 0x00, (byte) 0xaa, 0x00,
0x00, 0x55, (byte) 0xaa, 0x00,
0x55, 0x55, (byte) 0xaa, 0x00,
(byte) 0xaa, 0x55, (byte) 0xaa, 0x00,
(byte) 0xff, 0x55, (byte) 0xaa, 0x00,
0x00, (byte) 0xaa, (byte) 0xaa, 0x00,
0x55, (byte) 0xaa, (byte) 0xaa, 0x00,
(byte) 0xaa, (byte) 0xaa, (byte) 0xaa, 0x00,
(byte) 0xff, (byte) 0xaa, (byte) 0xaa, 0x00,
0x00, (byte) 0xff, (byte) 0xaa, 0x00,
0x55, (byte) 0xff, (byte) 0xaa, 0x00,
(byte) 0xaa, (byte) 0xff, (byte) 0xaa, 0x00,
(byte) 0xff, (byte) 0xff, (byte) 0xaa, 0x00,
0x00, 0x00, (byte) 0xff, 0x00,
0x55, 0x00, (byte) 0xff, 0x00,
(byte) 0xaa, 0x00, (byte) 0xff, 0x00,
(byte) 0xff, 0x00, (byte) 0xff, 0x00,
0x00, 0x55, (byte) 0xff, 0x00,
0x55, 0x55, (byte) 0xff, 0x00,
(byte) 0xaa, 0x55, (byte) 0xff, 0x00,
(byte) 0xff, 0x55, (byte) 0xff, 0x00,
0x00, (byte) 0xaa, (byte) 0xff, 0x00,
0x55, (byte) 0xaa, (byte) 0xff, 0x00,
(byte) 0xaa, (byte) 0xaa, (byte) 0xff, 0x00,
(byte) 0xff, (byte) 0xaa, (byte) 0xff, 0x00,
0x00, (byte) 0xff, (byte) 0xff, 0x00,
0x55, (byte) 0xff, (byte) 0xff, 0x00,
(byte) 0xaa, (byte) 0xff, (byte) 0xff, 0x00,
(byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00,
};
byte last_id = -1;
private ArrayList<UUID> tmpUUIDS = new ArrayList<>();
@ -477,7 +568,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
buf.putInt(timestamp); // 32-bit timestamp
buf.putShort((short) 0); // duration
buf.put((byte) 0x01); // type (0x01 = notification)
buf.putShort((short) 0x0001); // flags 0x0001 = ?
buf.putShort((short) 0x001f); // flags 0x0001 = ?
buf.put((byte) 0x04); // layout (0x04 = notification?)
buf.putShort(attributes_length); // total length of all attributes and actions in bytes
buf.put(attributes_count);
@ -506,7 +597,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
if (mForceProtocol) {
// ACTION
buf.put((byte) 0x01); // id
buf.put((byte) 0x00); // id
buf.put((byte) 0x04); // dismiss action
buf.put((byte) 0x01); // number attributes
buf.put((byte) 0x01); // attribute id (title)
@ -921,34 +1012,38 @@ public class PebbleProtocol extends GBDeviceProtocol {
byte result = buf.get();
mDevEventScreenshot = new GBDeviceEventScreenshot();
int version = buf.getInt();
if (result != 0 || version != 1) { // pebble time not yet
if (result != 0) {
return null;
}
mDevEventScreenshot.width = buf.getInt();
mDevEventScreenshot.height = buf.getInt();
mDevEventScreenshot.bpp = 1;
mDevEventScreenshot.clut = new byte[]{
0x00, 0x00, 0x00, 0x00, (byte) 0xff,
(byte) 0xff, (byte) 0xff, 0x00
};
mScreenshotRemaining = (mDevEventScreenshot.width * mDevEventScreenshot.height) / 8;
if (mScreenshotRemaining > 50000) {
mScreenshotRemaining = -1; // ignore too big values
return null;
if (version == 1) {
mDevEventScreenshot.bpp = 1;
mDevEventScreenshot.clut = clut_pebble;
} else {
mDevEventScreenshot.bpp = 8;
mDevEventScreenshot.clut = clut_pebbletime;
}
mScreenshotRemaining = (mDevEventScreenshot.width * mDevEventScreenshot.height * mDevEventScreenshot.bpp) / 8;
mDevEventScreenshot.data = new byte[mScreenshotRemaining];
length -= 13;
}
if (mScreenshotRemaining == -1) {
return null;
}
for (int i = 0; i < length; i++) {
byte corrected = reverseBits(buf.get());
byte corrected = buf.get();
if (mDevEventScreenshot.bpp == 1) {
corrected = reverseBits(corrected);
} else {
corrected = (byte) (corrected & 0b00111111);
}
mDevEventScreenshot.data[mDevEventScreenshot.data.length - mScreenshotRemaining + i] = corrected;
}
mScreenshotRemaining -= length;
LOG.info("Screenshot remaining bytes " + mScreenshotRemaining);
if (mScreenshotRemaining == 0) {

View File

@ -151,16 +151,16 @@ public class GB {
headerbuf.putInt(screenshot.width);
headerbuf.putInt(-screenshot.height);
headerbuf.putShort((short) 1); // planes
headerbuf.putShort((short) 1); // bit count
headerbuf.putShort((short) screenshot.bpp);
headerbuf.putInt(0); // compression
headerbuf.putInt(0); // length of pixeldata in byte (uncompressed=0)
headerbuf.putInt(0); // pixels per meter (x)
headerbuf.putInt(0); // pixels per meter (y)
headerbuf.putInt(2); // number of colors in CLUT
headerbuf.putInt(2); // numbers of used colors
headerbuf.putInt(screenshot.clut.length / 4); // number of colors in CLUT
headerbuf.putInt(0); // numbers of used colors
headerbuf.put(screenshot.clut);
fos.write(headerbuf.array());
int rowbytes = screenshot.width / 8;
int rowbytes = (screenshot.width * screenshot.bpp) / 8;
byte[] pad = new byte[rowbytes % 4];
for (int i = 0; i < screenshot.height; i++) {
fos.write(screenshot.data, rowbytes * i, rowbytes);