Peter Barker
4 years ago
committed by
Peter Barker
6 changed files with 142 additions and 25 deletions
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
#include "SIM_SMBusDevice.h" |
||||
|
||||
int SITL::SMBusDevice::rdwr(I2C::i2c_rdwr_ioctl_data *&data) |
||||
{ |
||||
// see if this is a block...
|
||||
const uint8_t addr = data->msgs[0].buf[0]; |
||||
if (blockname[addr] == nullptr) { |
||||
// not a block
|
||||
return I2CRegisters_16Bit::rdwr(data); |
||||
} |
||||
|
||||
// it is a block.
|
||||
if (data->nmsgs == 2) { |
||||
// data read request
|
||||
if (data->msgs[0].flags != 0) { |
||||
AP_HAL::panic("Unexpected flags"); |
||||
} |
||||
if (data->msgs[1].flags != I2C_M_RD) { |
||||
AP_HAL::panic("Unexpected flags"); |
||||
} |
||||
|
||||
data->msgs[1].buf[0] = value_lengths[addr]; |
||||
const uint8_t to_copy = MIN(data->msgs[1].len-1, value_lengths[addr]); |
||||
memcpy(&data->msgs[1].buf[1], values[addr], to_copy); |
||||
data->msgs[1].len = to_copy + 1; |
||||
return 0; |
||||
} |
||||
|
||||
if (data->nmsgs == 1) { |
||||
// data write request
|
||||
if (data->msgs[0].flags != 0) { |
||||
AP_HAL::panic("Unexpected flags"); |
||||
} |
||||
AP_HAL::panic("block writes not implemented"); |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
void SITL::SMBusDevice::add_block(const char *name, uint8_t reg, int8_t mode) |
||||
{ |
||||
// ::fprintf(stderr, "Adding block %u (0x%02x) (%s)\n", reg, reg, name);
|
||||
blockname[reg] = name; |
||||
if (mode == O_RDONLY || mode == O_RDWR) { |
||||
readable_blocks.set((uint8_t)reg); |
||||
} |
||||
if (mode == O_WRONLY || mode == O_RDWR) { |
||||
writable_blocks.set((uint8_t)reg); |
||||
} |
||||
} |
||||
|
||||
void SITL::SMBusDevice::set_block(uint8_t block, uint8_t *value, uint8_t valuelen) |
||||
{ |
||||
if (blockname[block] == nullptr) { |
||||
AP_HAL::panic("Setting un-named block %u", block); |
||||
} |
||||
// ::fprintf(stderr, "Setting %u (0x%02x) (%s) to 0x%02x (%c)\n", (unsigned)reg, (unsigned)reg, regname[reg], (unsigned)value, value);
|
||||
if (valuelen == 0) { |
||||
AP_HAL::panic("Zero-length values not permitted by spec"); |
||||
} |
||||
if (values[block] != nullptr) { |
||||
free(values[block]); |
||||
} |
||||
values[block] = (char*)malloc(valuelen); |
||||
memcpy(values[block], value, valuelen); |
||||
value_lengths[block] = valuelen; |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
#pragma once |
||||
|
||||
#include "SIM_I2CDevice.h" |
||||
|
||||
namespace SITL { |
||||
|
||||
class SMBusRegEnum : public I2CRegEnum { |
||||
}; |
||||
|
||||
class SMBusDevice : public I2CDevice, private I2CRegisters_16Bit { |
||||
public: |
||||
|
||||
SMBusDevice() : |
||||
I2CDevice(), |
||||
I2CRegisters_16Bit() |
||||
{ } |
||||
|
||||
void set_register(uint8_t reg, uint16_t value) { |
||||
I2CRegisters_16Bit::set_register(reg, value); |
||||
} |
||||
void set_register(uint8_t reg, int16_t value) { |
||||
I2CRegisters_16Bit::set_register(reg, value); |
||||
} |
||||
|
||||
uint16_t get_reg_value(uint8_t reg) { |
||||
return I2CRegisters_16Bit::get_reg_value(reg); |
||||
} |
||||
|
||||
|
||||
protected: |
||||
|
||||
int rdwr(I2C::i2c_rdwr_ioctl_data *&data) override; |
||||
|
||||
void set_block(uint8_t block, uint8_t *value, uint8_t valuelen); |
||||
void add_block(const char *name, uint8_t reg, int8_t mode); |
||||
|
||||
void set_block(uint8_t block, const char *value) { |
||||
set_block(block, (uint8_t*)value, strlen(value)); |
||||
} |
||||
|
||||
|
||||
void add_register(const char *name, uint8_t reg, int8_t mode) { |
||||
I2CRegisters_16Bit::add_register(name, reg, mode); |
||||
} |
||||
|
||||
private: |
||||
|
||||
const char *blockname[256]; |
||||
Bitmask<256> writable_blocks; |
||||
Bitmask<256> readable_blocks; |
||||
|
||||
// 256 pointers-to-malloced-values:
|
||||
char *values[256]; |
||||
uint8_t value_lengths[256]; |
||||
}; |
||||
|
||||
} // namespace SITL
|
Loading…
Reference in new issue