1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "dumpstate" 18 19 #include "DumpstateDevice.h" 20 21 #include "DumpstateUtil.h" 22 23 #include <errno.h> 24 #include <log/log.h> 25 #include <fcntl.h> 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 static const char base64[] = 31 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 32 static const char pad64 = '='; 33 34 using android::os::dumpstate::CommandOptions; 35 using android::os::dumpstate::DumpFileToFd; 36 using android::os::dumpstate::RunCommandToFd; 37 38 namespace android { 39 namespace hardware { 40 namespace dumpstate { 41 namespace V1_0 { 42 namespace implementation { 43 44 static void base64_output3(int out_fd, const unsigned char *src, int len) 45 { 46 dprintf(out_fd, "%c", base64[src[0] >> 2]); 47 dprintf(out_fd, "%c", base64[((src[0] & 0x03) << 4) | (src[1] >> 4)]); 48 if (len == 1) { 49 dprintf(out_fd, "=="); 50 return; 51 } 52 dprintf(out_fd, "%c", base64[((src[1] & 0x0F) << 2) | (src[2] >> 6)]); 53 if (len == 2) { 54 dprintf(out_fd, "="); 55 return; 56 } 57 dprintf(out_fd, "%c", base64[src[2] & 0x3F]); 58 } 59 60 static void fugu_dump_base64(int out_fd, const char *path) 61 { 62 63 dprintf(out_fd, "------ (%s) ------\n", path); 64 int fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); 65 if (fd < 0) { 66 dprintf(out_fd, "*** %s: %s\n\n", path, strerror(errno)); 67 return; 68 } 69 70 /* buffer size multiple of 3 for ease of use */ 71 unsigned char buffer[1200]; 72 int left = 0; 73 int count = 0; 74 for (;;) { 75 int ret = read(fd, &buffer[left], sizeof(buffer) - left); 76 if (ret <= 0) { 77 break; 78 } 79 left += ret; 80 int ofs = 0; 81 while (left > 2) { 82 base64_output3(out_fd, &buffer[ofs], 3); 83 left -= 3; 84 ofs += 3; 85 count += 4; 86 if (count > 72) { 87 dprintf(out_fd, "\n"); 88 count = 0; 89 } 90 } 91 if (left) { 92 memmove(buffer, &buffer[ofs], left); 93 } 94 } 95 close(fd); 96 97 if (!left) { 98 dprintf(out_fd, "\n------ end ------\n"); 99 return; 100 } 101 102 /* finish padding */ 103 count = left; 104 while (count < 3) { 105 buffer[count++] = 0; 106 } 107 base64_output3(out_fd, buffer, left); 108 109 dprintf(out_fd, "\n------ end ------\n"); 110 } 111 112 // Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow. 113 Return<void> DumpstateDevice::dumpstateBoard(const hidl_handle& handle) { 114 if (handle->numFds < 1) { 115 ALOGE("no FDs\n"); 116 return Void(); 117 } 118 119 int fd = handle->data[0]; 120 if (fd < 0) { 121 ALOGE("invalid FD: %d\n", handle->data[0]); 122 return Void(); 123 } 124 125 DumpFileToFd(fd, "INTERRUPTS", "/proc/interrupts"); 126 DumpFileToFd(fd, "last ipanic_console", "/data/dontpanic/ipanic_console"); 127 DumpFileToFd(fd, "last ipanic_threads", "/data/dontpanic/ipanic_threads"); 128 129 fugu_dump_base64(fd, "/dev/snd_atvr_mSBC"); 130 fugu_dump_base64(fd, "/dev/snd_atvr_pcm"); 131 132 return Void(); 133 } 134 135 } // namespace implementation 136 } // namespace V1_0 137 } // namespace dumpstate 138 } // namespace hardware 139 } // namespace android 140