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