i2c: bus manager
Change-Id: Ic2a7d3a4949a06a6e5f35dbb0b43d8239f92a370 Reviewed-on: https://review.haiku-os.org/c/haiku/+/2457 Reviewed-by: Jérôme Duval <jerome.duval@gmail.com> Reviewed-by: Rene Gollent <rene@gollent.com>
This commit is contained in:
parent
b9d640760e
commit
f6f8cb83e4
@ -2,10 +2,11 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers acpi ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers agp_gart ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers ata ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers config_manager ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers fdt ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers firewire ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers ata ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers i2c ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers isa ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers mmc ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel bus_managers pci ;
|
||||
|
184
src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp
Normal file
184
src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "I2CPrivate.h"
|
||||
|
||||
|
||||
I2CBus::I2CBus(device_node *node, uint8 id)
|
||||
:
|
||||
fNode(node),
|
||||
fID(id),
|
||||
fController(NULL),
|
||||
fCookie(NULL)
|
||||
{
|
||||
CALLED();
|
||||
device_node *parent = gDeviceManager->get_parent_node(node);
|
||||
status_t status = gDeviceManager->get_driver(parent,
|
||||
(driver_module_info **)&fController, &fCookie);
|
||||
gDeviceManager->put_node(parent);
|
||||
|
||||
if (status != B_OK)
|
||||
return;
|
||||
|
||||
fController->set_i2c_bus(fCookie, this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
I2CBus::~I2CBus()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CBus::InitCheck()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CBus::ExecCommand(i2c_op op, i2c_addr slaveAddress, const void *cmdBuffer,
|
||||
size_t cmdLength, void* dataBuffer, size_t dataLength)
|
||||
{
|
||||
CALLED();
|
||||
return fController->exec_command(fCookie, op, slaveAddress, cmdBuffer, cmdLength,
|
||||
dataBuffer, dataLength);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CBus::RegisterDevice(i2c_addr slaveAddress, char* hid, char** cid,
|
||||
acpi_handle acpiHandle)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
device_attr attrs[] = {
|
||||
// connection
|
||||
{ I2C_DEVICE_SLAVE_ADDR_ITEM, B_UINT16_TYPE, { ui16: slaveAddress }},
|
||||
|
||||
// description of peripheral drivers
|
||||
{ B_DEVICE_BUS, B_STRING_TYPE, { string: "i2c" }},
|
||||
|
||||
{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
|
||||
|
||||
{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }},
|
||||
|
||||
{ ACPI_DEVICE_CID_ITEM, B_STRING_TYPE, { string: cid[0] }},
|
||||
|
||||
{ ACPI_DEVICE_HANDLE_ITEM, B_UINT64_TYPE, { ui64: (addr_t)acpiHandle }},
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
return gDeviceManager->register_node(fNode, I2C_DEVICE_MODULE_NAME, attrs,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CBus::Scan()
|
||||
{
|
||||
CALLED();
|
||||
|
||||
fController->scan_bus(fCookie);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_init_bus(device_node *node, void **_bus)
|
||||
{
|
||||
CALLED();
|
||||
uint8 pathID;
|
||||
if (gDeviceManager->get_attr_uint8(node, I2C_BUS_PATH_ID_ITEM, &pathID,
|
||||
false) != B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
I2CBus *bus = new(std::nothrow) I2CBus(node, pathID);
|
||||
if (bus == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t result = bus->InitCheck();
|
||||
if (result != B_OK) {
|
||||
ERROR("failed to set up i2c bus object\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
*_bus = bus;
|
||||
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "bus/i2c/%d/bus_raw", pathID);
|
||||
|
||||
return gDeviceManager->publish_device(node, name, I2C_BUS_RAW_MODULE_NAME);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i2c_uninit_bus(void *_bus)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus *bus = (I2CBus *)_bus;
|
||||
delete bus;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
i2c_scan_bus(void *_bus)
|
||||
{
|
||||
I2CBus *bus = (I2CBus *)_bus;
|
||||
return bus->Scan();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
i2c_bus_exec_command(void* _bus, i2c_op op, i2c_addr slaveAddress,
|
||||
const void *cmdBuffer, size_t cmdLength, void* dataBuffer,
|
||||
size_t dataLength)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus* bus = (I2CBus*)_bus;
|
||||
return bus->ExecCommand(op, slaveAddress, cmdBuffer, cmdLength,
|
||||
dataBuffer, dataLength);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
i2c_bus_interface gI2CBusModule = {
|
||||
{
|
||||
{
|
||||
I2C_BUS_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
NULL, // supported devices
|
||||
NULL, // register node
|
||||
i2c_init_bus,
|
||||
i2c_uninit_bus,
|
||||
i2c_scan_bus, // register child devices
|
||||
NULL, // rescan
|
||||
},
|
||||
|
||||
i2c_bus_exec_command
|
||||
};
|
||||
|
143
src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp
Normal file
143
src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "I2CPrivate.h"
|
||||
|
||||
|
||||
I2CDevice::I2CDevice(device_node *node, I2CBus* bus, i2c_addr slaveAddress)
|
||||
:
|
||||
fNode(node),
|
||||
fBus(bus),
|
||||
fSlaveAddress(slaveAddress)
|
||||
{
|
||||
CALLED();
|
||||
}
|
||||
|
||||
|
||||
I2CDevice::~I2CDevice()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CDevice::InitCheck()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
I2CDevice::ExecCommand(i2c_op op, const void *cmdBuffer,
|
||||
size_t cmdLength, void* dataBuffer, size_t dataLength)
|
||||
{
|
||||
CALLED();
|
||||
return fBus->ExecCommand(op, fSlaveAddress, cmdBuffer, cmdLength,
|
||||
dataBuffer, dataLength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_init_device(device_node *node, void **_device)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus* bus;
|
||||
|
||||
{
|
||||
device_node *parent = gDeviceManager->get_parent_node(node);
|
||||
gDeviceManager->get_driver(parent, NULL, (void **)&bus);
|
||||
gDeviceManager->put_node(parent);
|
||||
}
|
||||
|
||||
uint16 slaveAddress;
|
||||
if (gDeviceManager->get_attr_uint16(node, I2C_DEVICE_SLAVE_ADDR_ITEM,
|
||||
&slaveAddress, false) != B_OK) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
I2CDevice *device = new(std::nothrow) I2CDevice(node, bus, slaveAddress);
|
||||
if (device == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t result = device->InitCheck();
|
||||
if (result != B_OK) {
|
||||
ERROR("failed to set up i2c device object\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
*_device = device;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i2c_uninit_device(void *_device)
|
||||
{
|
||||
CALLED();
|
||||
I2CDevice *device = (I2CDevice *)_device;
|
||||
delete device;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i2c_device_removed(void *_device)
|
||||
{
|
||||
CALLED();
|
||||
//I2CDevice *device = (I2CDevice *)_device;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_exec_command(i2c_device _device, i2c_op op, const void *cmdBuffer,
|
||||
size_t cmdLength, void* dataBuffer, size_t dataLength)
|
||||
{
|
||||
I2CDevice *device = (I2CDevice *)_device;
|
||||
return device->ExecCommand(op, cmdBuffer, cmdLength, dataBuffer, dataLength);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
{
|
||||
// Link to I2C bus.
|
||||
// I2C device driver must have I2C bus loaded, but it calls its
|
||||
// functions directly instead via official interface, so this
|
||||
// pointer is never read.
|
||||
module_info *dummy;
|
||||
return get_module(I2C_BUS_MODULE_NAME, &dummy);
|
||||
}
|
||||
case B_MODULE_UNINIT:
|
||||
return put_module(I2C_BUS_MODULE_NAME);
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i2c_device_interface gI2CDeviceModule = {
|
||||
{
|
||||
{
|
||||
I2C_DEVICE_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
NULL, // supported devices
|
||||
NULL, // register node
|
||||
i2c_init_device,
|
||||
(void (*)(void *)) i2c_uninit_device,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
(void (*)(void *)) i2c_device_removed
|
||||
},
|
||||
i2c_exec_command,
|
||||
};
|
102
src/add-ons/kernel/bus_managers/i2c/I2CModule.cpp
Normal file
102
src/add-ons/kernel/bus_managers/i2c/I2CModule.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "I2CPrivate.h"
|
||||
|
||||
|
||||
device_manager_info *gDeviceManager = NULL;
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
i2c_added_device(device_node *parent)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
int32 pathID = gDeviceManager->create_id(I2C_PATHID_GENERATOR);
|
||||
if (pathID < 0) {
|
||||
ERROR("cannot register i2c controller - out of path IDs\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
device_attr attributes[] = {
|
||||
// info about device
|
||||
{ B_DEVICE_BUS, B_STRING_TYPE, { string: "i2c" }},
|
||||
{ I2C_BUS_PATH_ID_ITEM, B_UINT8_TYPE, { ui8: (uint8)pathID }},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
TRACE("i2c_added_device parent %p\n", parent);
|
||||
|
||||
return gDeviceManager->register_node(parent, I2C_BUS_MODULE_NAME,
|
||||
attributes, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
i2c_register_device(i2c_bus _bus, i2c_addr slaveAddress, char* hid,
|
||||
char** cid, acpi_handle acpiHandle)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus* bus = (I2CBus*)_bus;
|
||||
return bus->RegisterDevice(slaveAddress, hid, cid, acpiHandle);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
i2c_for_controller_interface gI2CForControllerModule = {
|
||||
{
|
||||
{
|
||||
I2C_FOR_CONTROLLER_MODULE_NAME,
|
||||
0,
|
||||
&std_ops
|
||||
},
|
||||
|
||||
NULL, // supported devices
|
||||
i2c_added_device,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
i2c_register_device,
|
||||
};
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&gI2CForControllerModule,
|
||||
(module_info *)&gI2CBusModule,
|
||||
(module_info *)&gI2CDeviceModule,
|
||||
(module_info *)&gI2CBusRawModule,
|
||||
NULL
|
||||
};
|
||||
|
86
src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h
Normal file
86
src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef I2C_PRIVATE_H
|
||||
#define I2C_PRIVATE_H
|
||||
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <lock.h>
|
||||
#include <util/AutoLock.h>
|
||||
#include <i2c.h>
|
||||
|
||||
|
||||
//#define I2C_TRACE
|
||||
#ifdef I2C_TRACE
|
||||
# define TRACE(x...) dprintf("\33[33mi2c:\33[0m " x)
|
||||
#else
|
||||
# define TRACE(x...)
|
||||
#endif
|
||||
#define TRACE_ALWAYS(x...) dprintf("\33[33mi2c:\33[0m " x)
|
||||
#define ERROR(x...) TRACE_ALWAYS(x)
|
||||
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
|
||||
|
||||
#define I2C_SIM_MODULE_NAME "bus_managers/i2c/sim/driver_v1"
|
||||
|
||||
#define I2C_PATHID_GENERATOR "i2c/path_id"
|
||||
#define I2C_BUS_RAW_MODULE_NAME "bus_managers/i2c/bus/raw/device_v1"
|
||||
|
||||
|
||||
class I2CBus;
|
||||
class I2CDevice;
|
||||
|
||||
extern device_manager_info *gDeviceManager;
|
||||
extern struct device_module_info gI2CBusRawModule;
|
||||
extern i2c_bus_interface gI2CBusModule;
|
||||
extern i2c_device_interface gI2CDeviceModule;
|
||||
|
||||
class I2CDevice {
|
||||
public:
|
||||
I2CDevice(device_node* node, I2CBus* bus,
|
||||
i2c_addr slaveAddress);
|
||||
~I2CDevice();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
status_t ExecCommand(i2c_op op, const void *cmdBuffer,
|
||||
size_t cmdLength, void* dataBuffer,
|
||||
size_t dataLength);
|
||||
|
||||
private:
|
||||
device_node* fNode;
|
||||
I2CBus* fBus;
|
||||
i2c_addr fSlaveAddress;
|
||||
};
|
||||
|
||||
|
||||
class I2CBus {
|
||||
public:
|
||||
I2CBus(device_node *node, uint8 id);
|
||||
~I2CBus();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
status_t ExecCommand(i2c_op op, i2c_addr slaveAddress,
|
||||
const void *cmdBuffer, size_t cmdLength,
|
||||
void* dataBuffer, size_t dataLength);
|
||||
status_t Scan();
|
||||
status_t RegisterDevice(i2c_addr slaveAddress,
|
||||
char* hid, char** cid,
|
||||
acpi_handle acpiHandle);
|
||||
|
||||
private:
|
||||
device_node* fNode;
|
||||
uint8 fID;
|
||||
i2c_sim_interface* fController;
|
||||
void* fCookie;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // I2C_PRIVATE_H
|
11
src/add-ons/kernel/bus_managers/i2c/Jamfile
Normal file
11
src/add-ons/kernel/bus_managers/i2c/Jamfile
Normal file
@ -0,0 +1,11 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel bus_managers i2c ;
|
||||
|
||||
UsePrivateHeaders i2c ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
KernelAddon i2c :
|
||||
I2CBus.cpp
|
||||
I2CDevice.cpp
|
||||
I2CModule.cpp
|
||||
bus_raw.cpp
|
||||
;
|
154
src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp
Normal file
154
src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2020, Jérôme Duval. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "I2CPrivate.h"
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_init(void* driverCookie, void **_cookie)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus *bus = (I2CBus*)driverCookie;
|
||||
TRACE("i2c_bus_raw_init bus %p\n", bus);
|
||||
|
||||
*_cookie = bus;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i2c_bus_raw_uninit(void *bus)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_open(void *bus, const char *path, int openMode,
|
||||
void **handle_cookie)
|
||||
{
|
||||
CALLED();
|
||||
*handle_cookie = bus;
|
||||
TRACE("i2c_bus_raw_open bus %p\n", bus);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_close(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_free(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_control(void *_cookie, uint32 op, void *data, size_t length)
|
||||
{
|
||||
CALLED();
|
||||
I2CBus *bus = (I2CBus*)_cookie;
|
||||
|
||||
TRACE("i2c_bus_raw_control bus %p\n", bus);
|
||||
|
||||
|
||||
switch (op) {
|
||||
case I2CEXEC:
|
||||
{
|
||||
i2c_ioctl_exec exec;
|
||||
uint8 cmdBuffer[32];
|
||||
uint8 buffer[32];
|
||||
const void* userCmdBuffer = NULL;
|
||||
void* userBuffer = NULL;
|
||||
if (user_memcpy(&exec, data, sizeof(i2c_ioctl_exec)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
if (exec.cmdBuffer != NULL) {
|
||||
if (user_memcpy(cmdBuffer, exec.cmdBuffer, exec.cmdLength)
|
||||
!= B_OK) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
userCmdBuffer = exec.cmdBuffer;
|
||||
exec.cmdBuffer = cmdBuffer;
|
||||
}
|
||||
if (exec.buffer != NULL) {
|
||||
if (user_memcpy(buffer, exec.buffer, exec.bufferLength)
|
||||
!= B_OK) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
userBuffer = exec.buffer;
|
||||
exec.buffer = buffer;
|
||||
}
|
||||
|
||||
status_t status = bus->ExecCommand(exec.op, exec.addr,
|
||||
&exec.cmdBuffer, exec.cmdLength, exec.buffer,
|
||||
exec.bufferLength);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
exec.cmdBuffer = userCmdBuffer;
|
||||
if (exec.buffer != NULL) {
|
||||
if (user_memcpy(userBuffer, exec.buffer, exec.bufferLength)
|
||||
!= B_OK) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
exec.buffer = userBuffer;
|
||||
}
|
||||
|
||||
if (user_memcpy(data, &exec, sizeof(i2c_ioctl_exec)) != B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_read(void *cookie, off_t position, void *data,
|
||||
size_t *numBytes)
|
||||
{
|
||||
*numBytes = 0;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
i2c_bus_raw_write(void *cookie, off_t position,
|
||||
const void *data, size_t *numBytes)
|
||||
{
|
||||
*numBytes = 0;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
struct device_module_info gI2CBusRawModule = {
|
||||
{
|
||||
I2C_BUS_RAW_MODULE_NAME,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
|
||||
i2c_bus_raw_init,
|
||||
i2c_bus_raw_uninit,
|
||||
NULL, // removed
|
||||
|
||||
i2c_bus_raw_open,
|
||||
i2c_bus_raw_close,
|
||||
i2c_bus_raw_free,
|
||||
i2c_bus_raw_read,
|
||||
i2c_bus_raw_write,
|
||||
NULL, // io
|
||||
i2c_bus_raw_control,
|
||||
NULL, // select
|
||||
NULL // deselect
|
||||
};
|
Loading…
Reference in New Issue
Block a user