driverlog wip

Change-Id: Icbf1a6e45dcfa8b2dea21f9d2199d5283842cf7b
diff --git a/system/core/devmgr/devhost-rpc-server.c b/system/core/devmgr/devhost-rpc-server.c
index eec424f..72bc2c5 100644
--- a/system/core/devmgr/devhost-rpc-server.c
+++ b/system/core/devmgr/devhost-rpc-server.c
@@ -267,6 +267,30 @@
         memcpy(info->name, devhost_name, strlen(devhost_name));
         return sizeof(vfs_query_info_t) + strlen(devhost_name);
     }
+    case IOCTL_DEVICE_GET_DRIVER_LOG_FLAGS: {
+        if (!dev->driver) {
+            return ZX_ERR_NOT_SUPPORTED;
+        }
+        if (out_len < sizeof(uint32_t)) {
+            return ZX_ERR_BUFFER_TOO_SMALL;
+        }
+        *((uint32_t *)out_buf) = dev->driver->driver_rec->log_flags;
+        return ZX_OK;
+    }
+    case IOCTL_DEVICE_SET_DRIVER_LOG_FLAGS: {
+        if (!dev->driver) {
+            return ZX_ERR_NOT_SUPPORTED;
+        }
+        if (in_len < sizeof(uint64_t)) {
+            return ZX_ERR_BUFFER_TOO_SMALL;
+        }
+        uint32_t flags = dev->driver->driver_rec->log_flags;
+        uint64_t arg = *((uint64_t *)in_buf);
+        uint32_t set_flags = arg & UINT32_MAX;
+        uint32_t mask = arg >> 32;
+        dev->driver->driver_rec->log_flags = (flags & ~mask) | (set_flags & mask);
+        return ZX_OK;
+    }
     default: {
         size_t actual = 0;
         r = dev_op_ioctl(dev, op, in_buf, in_len, out_buf, out_len, &actual);
diff --git a/system/core/devmgr/devhost.c b/system/core/devmgr/devhost.c
index 0aa2651..fc5fd13 100644
--- a/system/core/devmgr/devhost.c
+++ b/system/core/devmgr/devhost.c
@@ -171,6 +171,7 @@
         goto done;
     }
 
+    drv->driver_rec = dr;
     drv->name = dn->payload.name;
     drv->ops = dr->ops;
     dr->driver = drv;
diff --git a/system/core/devmgr/devhost.h b/system/core/devmgr/devhost.h
index 7e915b1..2473926 100644
--- a/system/core/devmgr/devhost.h
+++ b/system/core/devmgr/devhost.h
@@ -30,6 +30,7 @@
 
 typedef struct zx_driver {
     const char* name;
+    zx_driver_rec_t* driver_rec;
     const zx_driver_ops_t* ops;
     void* ctx;
     const char* libname;
diff --git a/system/public/zircon/device/device.h b/system/public/zircon/device/device.h
index 4c65e9c..82b20c7 100644
--- a/system/public/zircon/device/device.h
+++ b/system/public/zircon/device/device.h
@@ -58,6 +58,21 @@
 #define IOCTL_DEVICE_DEBUG_RESUME \
     IOCTL(IOCTL_KIND_DEFAULT, IOCTL_FAMILY_DEVICE, 8)
 
+// Returns the log flags for driver bound to this device
+//   in: none
+//   out: uint32_t
+#define IOCTL_DEVICE_GET_DRIVER_LOG_FLAGS \
+    IOCTL(IOCTL_KIND_DEFAULT, IOCTL_FAMILY_DEVICE, 9)
+
+// Sets the log flags for driver bound to this device
+// Flags to set are in low 32 bits, mask for setting the flags
+// are in the high 32 bits
+//   in: uint64_t
+//   out: none
+#define IOCTL_DEVICE_SET_DRIVER_LOG_FLAGS \
+    IOCTL(IOCTL_KIND_DEFAULT, IOCTL_FAMILY_DEVICE, 10)
+
+
 // Indicates if there's data available to read,
 // or room to write, or an error condition.
 #define DEVICE_SIGNAL_READABLE ZX_USER_SIGNAL_0
@@ -89,3 +104,9 @@
 
 // ssize_t ioctl_device_sync(int fd);
 IOCTL_WRAPPER(ioctl_device_sync, IOCTL_DEVICE_SYNC);
+
+// ssize_t ioctl_device_get_log_flags(int fd, uint32_t* out);
+IOCTL_WRAPPER_OUT(ioctl_device_get_log_flags, IOCTL_DEVICE_GET_DRIVER_LOG_FLAGS, uint32_t);
+
+// ssize_t ioctl_device_set_log_flags(int fd, uint64_t in);
+IOCTL_WRAPPER_IN(ioctl_device_set_log_flags, IOCTL_DEVICE_SET_DRIVER_LOG_FLAGS, uint64_t);
diff --git a/system/uapp/driverlog/driverlog.c b/system/uapp/driverlog/driverlog.c
new file mode 100644
index 0000000..328b3a4
--- /dev/null
+++ b/system/uapp/driverlog/driverlog.c
@@ -0,0 +1,96 @@
+// Copyright 2016 The Fuchsia 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 <ddk/debug.h>
+#include <zircon/device/device.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void usage(void) {
+
+}
+
+int main(int argc, char **argv) {
+    int ret = 0;
+
+    if (argc < 2) {
+        usage();
+        return -1;
+    }
+
+    const char* path = argv[1];
+
+    int fd = open(path, O_RDWR);
+    if (fd < 0) {
+        fprintf(stderr, "could not open %s\n", path);
+        return -1;
+    }
+
+    if (argc == 2) {
+        uint32_t flags;
+        ret = ioctl_device_get_log_flags(fd, &flags);
+        if (ret < 0) {
+            fprintf(stderr, "ioctl_device_get_log_flags failed for %s\n", path);
+        } else {
+            if (flags & ZX_LOG_ERROR) {
+                printf("ERROR ");
+            }
+            if (flags & ZX_LOG_INFO) {
+                printf("INFO ");
+            }
+            if (flags & ZX_LOG_TRACE) {
+                printf("TRACE ");
+            }
+            if (flags & ZX_LOG_SPEW) {
+                printf("SPEW");
+            }
+            printf("\n");
+        }
+        goto out; 
+    }
+
+    uint32_t flags = 0;
+    uint32_t mask = 0;
+
+    for (int i = 2; i < argc; i++) {        
+        char* arg = argv[i];
+        char action = arg[0];
+        uint32_t flag = 0;
+
+        // check for leading + or -
+        if (action == '+' || action == '-') {
+            arg++;
+        }
+        if (!strcasecmp(arg, "e") || !strcasecmp(arg, "error")) {
+            flag = ZX_LOG_ERROR;
+        } else if (!strcasecmp(arg, "i") || !strcasecmp(arg, "info")) {
+            flag = ZX_LOG_INFO;
+        } else if (!strcasecmp(arg, "t") || !strcasecmp(arg, "trace")) {
+            flag = ZX_LOG_TRACE;
+        } else if (!strcasecmp(arg, "s") || !strcasecmp(arg, "spew")) {
+            flag = ZX_LOG_SPEW;
+        } else {
+            fprintf(stderr, "unknown flag %s\n", arg);
+            ret = -1;
+            goto out;
+        }
+
+        if (action == '-') {
+            mask |= flag;
+        } else if {
+            flags |= flag;
+            mask |= flag;
+        } 
+    }
+
+
+kkkk
+
+out:
+    close(fd);
+    return ret;
+}
diff --git a/system/uapp/driverlog/rules.mk b/system/uapp/driverlog/rules.mk
new file mode 100644
index 0000000..1c7b3d3
--- /dev/null
+++ b/system/uapp/driverlog/rules.mk
@@ -0,0 +1,19 @@
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+MODULE_GROUP := misc
+
+MODULE_TYPE := userapp
+
+MODULE_SRCS += \
+    $(LOCAL_DIR)/driverlog.c
+
+MODULE_LIBS := system/ulib/zircon system/ulib/fdio system/ulib/c
+
+MODULE_HEADER_DEPS := system/ulib/ddk
+
+include make/module.mk