1// Copyright 2017 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <assert.h> 6#include <stdint.h> 7#include <stdio.h> 8#include <stdlib.h> 9#include <string.h> 10#include <threads.h> 11#include <unistd.h> 12 13#include <ddk/binding.h> 14#include <ddk/debug.h> 15#include <ddk/device.h> 16#include <ddk/driver.h> 17#include <ddk/protocol/i2c.h> 18#include <ddk/protocol/platform-defs.h> 19#include <ddk/protocol/platform-device.h> 20 21#include <zircon/process.h> 22#include <zircon/syscalls.h> 23 24typedef struct { 25 zx_device_t* zxdev; 26 i2c_protocol_t i2c; 27 thrd_t thread; 28 bool done; 29} i2c_test_t; 30 31static void i2c_test_release(void* ctx) { 32 i2c_test_t* bus = ctx; 33 34 bus->done = true; 35 thrd_join(bus->thread, NULL); 36 free(bus); 37} 38 39static zx_protocol_device_t i2c_test_device_protocol = { 40 .version = DEVICE_OPS_VERSION, 41 .release = i2c_test_release, 42}; 43 44static void i2c_complete(zx_status_t status, i2c_op_t* ops, size_t cnt,void* cookie) { 45 if (status != ZX_OK) { 46 zxlogf(ERROR, "gauss-i2c-test i2c_complete error: %d\n", status); 47 } 48 ZX_ASSERT(cnt == 1); 49 if (ops[0].length != 8) { 50 zxlogf(ERROR, "gauss-i2c-test received %d bytes instead of 8\n", ops[0].length); 51 } 52 uint8_t* data = (uint8_t*)ops[0].buf; 53 zxlogf(INFO, "gauss-i2c-test: %02X %02X %02X %02X %02X %02X %02X %02X\n", data[0], data[1], 54 data[2], data[3], data[4], data[5], data[6], data[7]); 55} 56 57static int i2c_test_thread(void *arg) { 58 i2c_test_t* i2c_test = arg; 59 60 while (!i2c_test->done) { 61 char write_buf[1] = { 0 }; 62 i2c_write_read(&i2c_test->i2c, write_buf, sizeof(write_buf), 8, i2c_complete, NULL); 63 sleep(1); 64 } 65 66 return 0; 67} 68 69static zx_status_t i2c_test_bind(void* ctx, zx_device_t* parent) { 70 i2c_test_t* i2c_test = calloc(1, sizeof(i2c_test_t)); 71 if (!i2c_test) { 72 return ZX_ERR_NO_MEMORY; 73 } 74 75 if (device_get_protocol(parent, ZX_PROTOCOL_I2C, &i2c_test->i2c) != ZX_OK) { 76 free(i2c_test); 77 return ZX_ERR_NOT_SUPPORTED; 78 } 79 80 device_add_args_t args = { 81 .version = DEVICE_ADD_ARGS_VERSION, 82 .name = "gauss-i2c-test", 83 .ctx = i2c_test, 84 .ops = &i2c_test_device_protocol, 85 .flags = DEVICE_ADD_NON_BINDABLE, 86 }; 87 88 zx_status_t status = device_add(parent, &args, NULL); 89 if (status != ZX_OK) { 90 free(i2c_test); 91 return status; 92 } 93 94 thrd_create_with_name(&i2c_test->thread, i2c_test_thread, i2c_test, "i2c_test_thread"); 95 return ZX_OK; 96} 97 98static zx_driver_ops_t i2c_test_driver_ops = { 99 .version = DRIVER_OPS_VERSION, 100 .bind = i2c_test_bind, 101}; 102 103ZIRCON_DRIVER_BEGIN(gauss_i2c_test, i2c_test_driver_ops, "zircon", "0.1", 4) 104 BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV), 105 BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GOOGLE), 106 BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GAUSS), 107 BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_GAUSS_I2C_TEST), 108ZIRCON_DRIVER_END(gauss_i2c_test) 109