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