/* dspcrashd.c ** ** Copyright 2010, The Android Open Source Project ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** * Neither the name of Google Inc. nor the names of its contributors may ** be used to endorse or promote products derived from this software ** without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <time.h> #include <sys/klog.h> #include <cutils/properties.h> #define KLOG_BUF_SHIFT 17 /* CONFIG_LOG_BUF_SHIFT from our kernel */ #define KLOG_BUF_LEN (1 << KLOG_BUF_SHIFT) char *props[] = { "ro.product.name", "ro.build.id", "ro.build.date", "ro.serialno", "ro.baseband", 0, }; char *dashes = "---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n"; void dump_dmesg(int fd) { char buffer[KLOG_BUF_LEN + 1]; char *p = buffer; ssize_t ret; int n, op; n = klogctl(KLOG_READ_ALL, buffer, KLOG_BUF_LEN); if (n < 0) return; buffer[n] = '\0'; while((ret = write(fd, p, n))) { if (ret < 0) { if (errno == EINTR) continue; return; } p += ret; n -= ret; } return 0; } void dump_info(int fd) { char buf[4096]; char val[PROPERTY_VALUE_MAX]; char **p = props; write(fd, dashes, strlen(dashes)); while (*p) { property_get(*p,val,""); sprintf(buf,"%s: %s\n", *p, val); write(fd, buf, strlen(buf)); p++; } write(fd, dashes, strlen(dashes)); dump_dmesg(fd); write(fd, dashes, strlen(dashes)); } void dump_dsp_state(int dsp) { int fd, r; char name[128]; char buf[128*1024]; sprintf(name,"/sdcard/dsp.crash.%d.img", (int) time(0)); fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd < 0) return; for (;;) { r = read(dsp, buf, sizeof(buf)); if (r == 0) break; if (r < 0) { if (errno == EINTR) continue; break; } write(fd, buf, r); } dump_info(fd); close(fd); fd = open("/dev/kmsg", O_WRONLY); if (fd >= 0) { sprintf(buf,"*** WROTE DSP RAMDUMP TO %s ***\n",name); write(fd, buf, strlen(buf)); close(fd); } } int main(int argc, char **argv) { int fd; fd = open("/dev/dsp_debug", O_RDWR); if (fd < 0) return -1; write(fd, "wait-for-crash", 14); dump_dsp_state(fd); sync(); sync(); sync(); write(fd, "continue-crash", 14); close(fd); for (;;) sleep(100); return 0; }