How to change LED trigger? - linux

I have register in BSP's the LED:
static struct gpio_led ic_leds[] = {
{
.name = "led1:green",
.gpio = USER_LED,
.default_trigger = "heartbeat",
.active_low = 1,
},
};
static struct gpio_led_platform_data ic_led_info = {
.num_leds = ARRAY_SIZE(ic_leds),
.leds = ic_leds,
};
static struct platform_device ic_leds_device = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &ic_led_info,
},
};
static void __init ic_add_device_leds(void)
{
platform_device_register(&ic_leds_device);
}
How can I change the trigger in run time? I know that it's possible with sysfs, but maybe exist another way?

echo "thetriggeryouwant" > /sys/class/leds/someled/trigger
where thetriggeryouwant is for example phy0rx and someled is the name of the led you want to change the trigger for.
To get all available triggers for that led, you can cat the file:
cat /sys/class/leds/someled/trigger
gives for example:
[none] timer oneshot mtd nand-disk heartbeat backlight gpio cpu cpu0 cpu1 activity default-on 2188000.ethernet-2:00:link 2188000.ethernet-2:00:100Mbps 2188000.ethernet-2:00:10Mbps
where the item in brackets ([none]) denotes the current trigger.

Related

Passing a std::unique_ptr as a void* parameter to a function (CPtrArray::Add)

My code:
void CAssignSelectedColumnDlg::AddColumnData(CString strHeading, CStringArray* pAryStrNames, int iColumnIndex, int iCustomIndex /*-1*/, BOOL bFixedCustomType /*FALSE*/)
{
//COLUMN_DATA_S *psData = nullptr;
//psData = new COLUMN_DATA_S;
auto psData = std::make_unique<COLUMN_DATA_S>();
if (psData != nullptr)
{
// Note: we don't "own" pAryStrNames
psData->strHeading = strHeading;
psData->pAryStrNames = pAryStrNames;
psData->sActionListInfo.byColumnIndex = iColumnIndex;
psData->sActionListInfo.byCustomIndex = iCustomIndex;
psData->sActionListInfo.bFixedCustomType = bFixedCustomType ? true : false;
m_aryPtrColumnData.Add(psData);
}
}
Code analysis was suggesting I use std::make_unique instead of new. So I adjusted teh code but now get a compile error. I tried to find a suitable approach:
No suitable conversion function from std::unique_ptr<COLUMN_DATA_S>, std::default_delete<COLUMN_DATA_S>> to void * exists.
The function in question is CPtrArray::Add. I am still trying to gras the smart pointers and their usage in a context like this.
Note that we should not be deleting the pointer when the function ends. The deletion of the collection is done in a dialog event handler.

How do I find glibc.so on linux distro to dynamically load it

I'm trying to dynamically load glibc under ubuntu (and ideally other linux distros).
The aim is to call seteuid.
I'm not certain what the correct method is to identify the path.
When running a find command I don't even see glib.so but I do see lib.so.
/usr/lib/x86_64-linux-gnu/libc.so
Is this the correct file?
If it is the correct file what is the correct way if find it on any system (hardcoding the path would be a last resort).
Statically linking isn't an option as I'm calling the method from Dart using ffi.
So I found the answer:
var path = 'libc.so.6';
Looks like its on the path and contains the seteuid method.
This is the final code I ended up with:
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:dcli/dcli.dart';
// on systems with _POSIX_SAVED_IDS defined
typedef setEffectiveUID_func = Int32 Function(Uint32 effectiveUID);
typedef setEffectiveUID = int Function(int effectiveUID);
/// on other systems.
/// sets the effective and real uids.
typedef setUID_func = Int32 Function(Uint32 realUID, Uint32 effectiveUID);
typedef setUID = int Function(int realUID, int effectiveUID);
class Priviliges {
static final Priviliges _self = Priviliges._internal();
DynamicLibrary dylib;
// the logged in user's original UID
int userUID;
/// true if we are running under sudo.
bool sudo;
/// I'm confused.
int realUID;
/// The user's effective UID when the script started.
/// If they are running as sudo then this will be root.
int originalEffectiveUID;
/// Used to track what UID is currently in effect.
int currentEffectiveUID;
factory Priviliges() => _self;
Priviliges._internal() {
var path = 'libc.so.6';
if (Platform.isMacOS) path = '/usr/lib/libSystem.dylib';
if (Platform.isWindows) path = r'primitives_library\Debug\primitives.dll';
dylib = DynamicLibrary.open(path);
realUID = _realUID;
var sudo_uid = env['SUDO_UID'];
if (sudo_uid != null) {
sudo = true;
userUID = int.tryParse(sudo_uid);
} else {
/// we aren't running sudo
sudo = false;
userUID = realUID;
}
originalEffectiveUID = _effectiveUID;
currentEffectiveUID = originalEffectiveUID;
}
int get _effectiveUID {
final geteuidPointer =
dylib.lookup<NativeFunction<getEffectiveUID_func>>('geteuid');
final geteuid = geteuidPointer.asFunction<getEffectiveUID>();
var uid = geteuid();
print('get effiective guid=$uid');
return uid;
}
set _effectiveUID(int effectiveUID) {
print('setting effective to $effectiveUID');
var result = -1;
try {
final seteuidPointer =
dylib.lookup<NativeFunction<setEffectiveUID_func>>('seteuid');
final seteuid = seteuidPointer.asFunction<setEffectiveUID>();
print(blue('settting effectiveUID =$effectiveUID'));
result = seteuid(effectiveUID);
} on ArgumentError catch (_) {
// seteuid isn't available so lets try setreuid
final setreuidPointer =
dylib.lookup<NativeFunction<setUID_func>>('setreuid');
final setreuid = setreuidPointer.asFunction<setUID>();
result = setreuid(-1, effectiveUID);
}
if (result != 0) {
throw PriviligesException('Unable to set the Effective UID: $result');
}
}
}
class PriviligesException extends DCliException {
PriviligesException(String message) : super(message);
}

Difference between spi_driver.id_table and spi_driver.driver.of_match_table

I'm currently trying to understand how linux drivers work. As far as I know, A driver's probe/init function is called when the kernel parses the corresponding .compatible string in the device tree. However, in the arizona-spi driver it looks like there are multiple compatible strings referenced in different members:
static const struct spi_device_id arizona_spi_ids[] = {
{ "wm5102", WM5102 },
{ "wm5110", WM5110 },
{ },
};
MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
static struct spi_driver arizona_spi_driver = {
.driver = {
.name = "arizona",
.owner = THIS_MODULE,
.pm = &arizona_pm_ops,
// Contains e.g. "wlf,wm5102"
.of_match_table = of_match_ptr(arizona_of_match),
},
.probe = arizona_spi_probe,
.remove = arizona_spi_remove,
.id_table = arizona_spi_ids, // Contains "wm5102" and "wm5110"
};
This is an excerpt from here.
So what is the difference between arizona_spi_driver.id_table and arizona_spi_driver.driver.of_match_table?
There are several mechanism for driver matching. The id_table is intended to be used for finding a match from stripped device-tree entries (without vendor part), while of_match_table is used to find a match from full device-tree entries (the ones with vendor part).
If you check, arizona_of_match is defined as this:
const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{},
};
wlf is the vendor part for this case, while arizona_spi_ids doesn't contain the vendor part.
Hence, if you have something like this in your device tree:
compatible = "myvendor,wm5102"
Your device will match against id_table but not against of_match_table since the vendor is different.
The kernel will do matching against of_match_table first before check id_table (see spi_get_device_id in here). The device matching priority is: of_match_table > acpi_driver > id_table.

Linux kernel driver same device on different buses?

Is there an example of same device using different buses, for example spi and i2c (simultaneously, depending on the choice)?
I am interested in a device that have some common routines, but uses different read/write functions.
For example an adc that has common function for calibration or triggering (never seen this in kernel adc drivers, but why not?), but different functions to read samples from different sources.
How such driver can be realized?
Should i do something like this in my module? :
static struct i2c_driver my_i2c_driver = {
.driver = {
.name = "my-i2c-driver",
},
.probe = my_i2c_driver_probe,
.remove = my_i2c_driver_remove,
};
static struct spi_driver my_spi_driver = {
.driver = {
.name = "my-spi-driver",
},
.probe = my_spi_driver_probe,
.remove = my_spi_driver_remove,
};
etc... for read/write, ops
I'm interested in theory, even if the "no need", "no one does that."
Actually in 3.10.25 kernel there is such an example,
A ST magnetometer LIS3MDL wich has indeed two interface i2c/spi, controlled via gpio input.
With drivers included in kernel official tree, located in drivers/iio/magnetometer.
With 2 separate driver modules located in st_magn_i2c.c and st_magn_spi.c
st_magn_i2c.c:
static struct spi_driver st_magn_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-magn-spi",
},
.probe = st_magn_spi_probe,
.remove = st_magn_spi_remove,
.id_table = st_magn_id_table,
};
st_magn_spi.c:
static struct i2c_driver st_magn_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-magn-i2c",
},
.probe = st_magn_i2c_probe,
.remove = st_magn_i2c_remove,
.id_table = st_magn_id_table,
};
Such devices some times happens - for example PCA2129T RTC.
So in assume this is an example i was almost looking for, though i wanted something more trickier (like a USB and something else) or some basic lead.

Should I use CRITICAL_SECTION or not?

I have a program which has a Ui with which users choose the way to display and do small configurations. It also has a background procedure, which continuously reads data from the network and update the data to display.
Now I put them in one process:
background procedure:
STATE MainWindow::Rcv()
{
DeviceMAP::iterator dev;
for(dev= dev_map.begin(); dev!= dev_map.end(); dev++)
{
dev->second.rcvData();//receive data from the network, the time can be ignored.
BitLog* log = new BitLog();
dev->second.parseData(log);
LogItem* logItem = new LogItem();
logItem->time = QString::fromLocal8Bit(log->rcvTime.c_str());
logItem->name = QString::fromLocal8Bit(log->basicInfo.getName().c_str());
logItem->PIN = QString::fromLocal8Bit(log->basicInfo.getPIN().c_str()).toShort();
delete log;
add_logItem(logItem);
}
return SUCCESS;
}
add_logItem:
void MainWindow::add_logItem(LogItem* logItem)
{
writeToFile(logItem);
Device* r = getDevbyPIN(QString::number(logItem->PIN));
if(r == NULL)return;
devInfo_inside_widget::States state = logItem->state;
bool bool_list[portsNum_X];
for(int i =0; i < portsNum_X; i++)
{
bool_list[i] = 0;
}
for(int i = 0; i < portsNum; i++)
{
bool_list[i] = (logItem->BITS[i/8] >> (7 - i%8)) & 0x1;
}
r->refresh(state, logItem->time, bool_list);//update data inside...state, time , BITS...
IconLabel* icl = getIConLabelByDev(r);//update data
icl->refresh(state);
logDisplayQueue.enqueue(logItem);//write queue here
int size = logDisplayQueue.size();
if(size > 100)
{
logDisplayQueue.dequeue();//write queue here
}
}
The section above has not dealt with any ui operations yet, but when user push a radio button in the ui, the program has to filter the data in the queue and display it in the table widget:
ui operations:
void MainWindow::filter_log_display(bool bol)
{
row_selectable = false;
ui->tableWidget->setRowCount(0);//delete table items all
row_selectable = true;
int size_1 = logDisplayQueue.size() - 1;
ui->tableWidget->verticalScrollBar()->setSliderPosition(0);
if(size_1+1 < 100)
{
ui->tableWidget->setRowCount(size_1 + 1);
}
else
{
ui->tableWidget->setRowCount(100);//display 100 rows at most
}
if(bol)//filter from logDisplayQueue and display unworking-state-log rows
{
int index = 0;
for(int queue_i = size_1; queue_i >= 0; queue_i--)
{
LogItem* logItem = (LogItem*)logDisplayQueue.at(queue_i); // read queue here
if(logItem->state == STATE_WORK || logItem->state == STATE_UN)continue;
QString BITS_str = bits2Hexs(logItem->BITS);
ui->tableWidget->setItem(index, 0, new QTableWidgetItem(logItem->time));//time
ui->tableWidget->setItem(index, 1, new QTableWidgetItem(logItem->name));//name
ui->tableWidget->setItem(index, 2, new QTableWidgetItem(BITS_str));//BITS
if(queue_i == oldRowItemNo)ui->tableWidget->selectRow(index);
index++;
}
ui->tableWidget->setRowCount(index);
}
else//display all rows
{
for(int queue_i = size_1, index = 0; queue_i >= 0; queue_i--, index++)
{
LogItem* logItem = (LogItem*)logDisplayQueue.at(queue_i); //read queue here
QString BITS_str = bits2Hexs(logItem->BITS);//
finish = clock();
ui->tableWidget->setItem(index, 0, new QTableWidgetItem(logItem->time));//time
ui->tableWidget->setItem(index, 1, new QTableWidgetItem(logItem->name));//name
ui->tableWidget->setItem(index, 2, new QTableWidgetItem(BITS_str));//BITS
if(queue_i == oldRowItemNo)ui->tableWidget->selectRow(index);
}
}
}
So the queue is quite samll and the background procedure is quite frequent(nearly 500 times per sec). That is, the queue will be written 500 times in 1 sec, but displayed time from time by the user.
I want to split the functions into two threads and run them together, one rev and update data, one display.
If i do not use any lock or mutex, the user may get the wrong data, but if i force the write-data procedure enter critical section and leave critical section everytime, it will be a heavy overload. :)
Should I use CRITICAL_SECTION or something else, any suggestions related?(my words could be verbose for you :) , i only hope for some hints :)
I'd put "Recv" function in another QObject derived class, put it under other QThread not main gui thread and connect "logItemAdded(LogItem* item)" signal to main window's "addLogItem(LogItem* item)" slot.
for just quick and dirty hint my conceptual code follows.
#include <QObject>
class Logger : public QObject
{
Q_OBJECT
public:
Logger(QObject* parent=0);
virtual ~Logger();
signals:
void logItemAdded(LogItem* logItem);
public slots:
protected:
void Rcv()
{
// ...
// was "add_logItem(logItem)"
emit logItemAdded(logItem);
}
};
MainWindow::MainWindow(...)
{
Logger logger = new Logger;
// setup your logger
QThread* thread = new QThread;
logger->moveToThread(thread);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
Hope this helps.
Good luck.

Resources