1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
225a536efa5b5f5d973232846d5fe6818df84ab5dcYuriy Zabroda#include <errno.h>
235a536efa5b5f5d973232846d5fe6818df84ab5dcYuriy Zabroda#include <sys/types.h>
245a536efa5b5f5d973232846d5fe6818df84ab5dcYuriy Zabroda#include <sys/wait.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26414ff7d98ac8d7610a26206335954ad15f43f3acDavid 'Digit' Turner#include "fdevent.h"
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/fb.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/mman.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* TODO:
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** - sync with vsync to avoid tearing
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
36154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin/* This version number defines the format of the fbinfo struct.
37154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin   It must match versioning in ddms where this data is consumed. */
38154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin#define DDMS_RAWIMAGE_VERSION 1
39154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavinstruct fbinfo {
40154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int version;
41154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int bpp;
42154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int size;
43154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int width;
44154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int height;
45154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int red_offset;
46154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int red_length;
47154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int blue_offset;
48154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int blue_length;
49154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int green_offset;
50154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int green_length;
51154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int alpha_offset;
52154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    unsigned int alpha_length;
53154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin} __attribute__((packed));
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid framebuffer_service(int fd, void *cookie)
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
57154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    struct fbinfo fbinfo;
580715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    unsigned int i;
590715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    char buf[640];
600715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    int fd_screencap;
610715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    int w, h, f;
620715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    int fds[2];
630715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian
640715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if (pipe(fds) < 0) goto done;
650715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian
660715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    pid_t pid = fork();
670715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if (pid < 0) goto done;
680715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian
690715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if (pid == 0) {
700715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        dup2(fds[1], STDOUT_FILENO);
710715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        close(fds[0]);
720715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        close(fds[1]);
730715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        const char* command = "screencap";
740715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        const char *args[2] = {command, NULL};
750715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        execvp(command, (char**)args);
760715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian        exit(1);
770715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    }
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
790715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    fd_screencap = fds[0];
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
810715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    /* read w, h & format */
820715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if(readx(fd_screencap, &w, 4)) goto done;
830715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if(readx(fd_screencap, &h, 4)) goto done;
840715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if(readx(fd_screencap, &f, 4)) goto done;
8504bee29ad979ca770677338e343869a0d5662cfbRebecca Schultz Zavin
86154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    fbinfo.version = DDMS_RAWIMAGE_VERSION;
87c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian    /* see hardware/hardware.h */
88c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian    switch (f) {
89c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        case 1: /* RGBA_8888 */
90c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.bpp = 32;
91c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.size = w * h * 4;
92c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.width = w;
93c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.height = h;
94c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_offset = 0;
95c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_length = 8;
96c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_offset = 8;
97c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_length = 8;
98c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_offset = 16;
99c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_length = 8;
100c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_offset = 24;
101c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_length = 8;
102c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            break;
103c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        case 2: /* RGBX_8888 */
104c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.bpp = 32;
105c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.size = w * h * 4;
106c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.width = w;
107c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.height = h;
108c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_offset = 0;
109c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_length = 8;
110c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_offset = 8;
111c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_length = 8;
112c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_offset = 16;
113c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_length = 8;
114c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_offset = 24;
115c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_length = 0;
116c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            break;
117c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        case 3: /* RGB_888 */
118c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.bpp = 24;
119c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.size = w * h * 3;
120c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.width = w;
121c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.height = h;
122c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_offset = 0;
123c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_length = 8;
124c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_offset = 8;
125c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_length = 8;
126c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_offset = 16;
127c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_length = 8;
128c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_offset = 24;
129c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_length = 0;
130c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            break;
131c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        case 4: /* RGB_565 */
132c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.bpp = 16;
133c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.size = w * h * 2;
134c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.width = w;
135c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.height = h;
136c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_offset = 11;
137c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_length = 5;
138c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_offset = 5;
139c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_length = 6;
140c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_offset = 0;
141c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_length = 5;
142c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_offset = 0;
143c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_length = 0;
144c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            break;
145c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        case 5: /* BGRA_8888 */
146c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.bpp = 32;
147c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.size = w * h * 4;
148c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.width = w;
149c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.height = h;
150c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_offset = 16;
151c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.red_length = 8;
152c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_offset = 8;
153c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.green_length = 8;
154c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_offset = 0;
155c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.blue_length = 8;
156c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_offset = 24;
157c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            fbinfo.alpha_length = 8;
158c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian           break;
159c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian        default:
160c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian            goto done;
161c1fbf7c1638cb4f1f139edf74562fcfbaa6f3435Mathias Agopian    }
1620715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian
1630715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    /* write header */
164154b7d7de4071ed73cde81eef3af47d1a24d7c6bRebecca Schultz Zavin    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1660715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    /* write data */
1670715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    for(i = 0; i < fbinfo.size; i += sizeof(buf)) {
1680715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian      if(readx(fd_screencap, buf, sizeof(buf))) goto done;
1690715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian      if(writex(fd, buf, sizeof(buf))) goto done;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1710715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done;
1720715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done;
17304bee29ad979ca770677338e343869a0d5662cfbRebecca Schultz Zavin
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone:
1755a536efa5b5f5d973232846d5fe6818df84ab5dcYuriy Zabroda    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
1765a536efa5b5f5d973232846d5fe6818df84ab5dcYuriy Zabroda
1770715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    close(fds[0]);
1780715f91223b2f7a91ea08bfa95998d846e7977cfMathias Agopian    close(fds[1]);
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
181