1 /* 2 * Copyright 2020, Jérôme Duval. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "I2CPrivate.h" 8 9 #include <kernel.h> 10 #include <StackOrHeapArray.h> 11 12 13 static status_t 14 i2c_bus_raw_init(void* driverCookie, void **_cookie) 15 { 16 CALLED(); 17 I2CBus *bus = (I2CBus*)driverCookie; 18 TRACE("i2c_bus_raw_init bus %p\n", bus); 19 20 *_cookie = bus; 21 return B_OK; 22 } 23 24 25 static void 26 i2c_bus_raw_uninit(void *bus) 27 { 28 } 29 30 31 static status_t 32 i2c_bus_raw_open(void *bus, const char *path, int openMode, 33 void **handle_cookie) 34 { 35 CALLED(); 36 *handle_cookie = bus; 37 TRACE("i2c_bus_raw_open bus %p\n", bus); 38 39 return B_OK; 40 } 41 42 43 static status_t 44 i2c_bus_raw_close(void *cookie) 45 { 46 return B_OK; 47 } 48 49 50 static status_t 51 i2c_bus_raw_free(void *cookie) 52 { 53 return B_OK; 54 } 55 56 57 static status_t 58 i2c_bus_raw_control(void *_cookie, uint32 op, void *data, size_t length) 59 { 60 CALLED(); 61 I2CBus *bus = (I2CBus*)_cookie; 62 63 TRACE("i2c_bus_raw_control bus %p\n", bus); 64 65 66 switch (op) { 67 case I2CEXEC: 68 { 69 i2c_ioctl_exec exec; 70 const void* userCmdBuffer = NULL; 71 void* userBuffer = NULL; 72 if (user_memcpy(&exec, data, sizeof(i2c_ioctl_exec)) != B_OK) 73 return B_BAD_ADDRESS; 74 75 if (exec.cmdBuffer == NULL) 76 exec.cmdLength = 0; 77 if (exec.buffer == NULL) 78 exec.bufferLength = 0; 79 BStackOrHeapArray<uint8, 32> cmdBuffer(exec.cmdLength); 80 BStackOrHeapArray<uint8, 32> buffer(exec.bufferLength); 81 if (!cmdBuffer.IsValid() || !buffer.IsValid()) 82 return B_NO_MEMORY; 83 84 if (exec.cmdBuffer != NULL) { 85 if (!IS_USER_ADDRESS(exec.cmdBuffer) 86 || user_memcpy(cmdBuffer, exec.cmdBuffer, exec.cmdLength) 87 != B_OK) { 88 return B_BAD_ADDRESS; 89 } 90 userCmdBuffer = exec.cmdBuffer; 91 exec.cmdBuffer = cmdBuffer; 92 } 93 if (exec.buffer != NULL) { 94 if (!IS_USER_ADDRESS(exec.buffer) 95 || user_memcpy(buffer, exec.buffer, exec.bufferLength) 96 != B_OK) { 97 return B_BAD_ADDRESS; 98 } 99 userBuffer = exec.buffer; 100 exec.buffer = buffer; 101 } 102 103 status_t status = bus->AcquireBus(); 104 if (status != B_OK) 105 return status; 106 107 status = bus->ExecCommand(exec.op, exec.addr, 108 exec.cmdBuffer, exec.cmdLength, exec.buffer, 109 exec.bufferLength); 110 bus->ReleaseBus(); 111 112 if (status != B_OK) 113 return status; 114 115 exec.cmdBuffer = userCmdBuffer; 116 if (exec.buffer != NULL) { 117 if (user_memcpy(userBuffer, exec.buffer, exec.bufferLength) 118 != B_OK) { 119 return B_BAD_ADDRESS; 120 } 121 exec.buffer = userBuffer; 122 } 123 124 if (user_memcpy(data, &exec, sizeof(i2c_ioctl_exec)) != B_OK) 125 return B_BAD_ADDRESS; 126 127 return B_OK; 128 } 129 } 130 131 return B_ERROR; 132 } 133 134 135 static status_t 136 i2c_bus_raw_read(void *cookie, off_t position, void *data, 137 size_t *numBytes) 138 { 139 *numBytes = 0; 140 return B_ERROR; 141 } 142 143 144 static status_t 145 i2c_bus_raw_write(void *cookie, off_t position, 146 const void *data, size_t *numBytes) 147 { 148 *numBytes = 0; 149 return B_ERROR; 150 } 151 152 153 struct device_module_info gI2CBusRawModule = { 154 { 155 I2C_BUS_RAW_MODULE_NAME, 156 0, 157 NULL 158 }, 159 160 i2c_bus_raw_init, 161 i2c_bus_raw_uninit, 162 NULL, // removed 163 164 i2c_bus_raw_open, 165 i2c_bus_raw_close, 166 i2c_bus_raw_free, 167 i2c_bus_raw_read, 168 i2c_bus_raw_write, 169 NULL, // io 170 i2c_bus_raw_control, 171 NULL, // select 172 NULL // deselect 173 }; 174