I am new to device drivers and I was learning this container_of and dev_get_drvdata and came across this driver.I removed some partof this driver so as to make it compact.
static void tsl4531_polling_worker(struct work_struct *work)
{
u8 buf[2];
struct tsl4531_data *data = container_of(to_delayed_work(work),
struct tsl4531_data, work);
mutex_lock(&data->update_lock);
buf[0] = DEVICE_LIGHT;
buf[1] = GET_REQUEST;
sam4l_send_request(data->pdata.sam4l,2,buf);
mutex_unlock(&data->update_lock);
}
static ssize_t store_enable_value(struct device *dev,struct device_attribute *devattr,const char *buf,size_t count){
struct tsl4531_data *data = dev_get_drvdata(dev);
if((buf[0] == '1') && (!tsl4531_enabled)) {
schedule_delayed_work(&data->work, msecs_to_jiffies(50));
tsl4531_enabled = 1;
} else if (buf[0] == '0'){
tsl4531_enabled = 0;
cancel_delayed_work_sync(&data->work);
tsl4531_lux = 0;
}
return count;
}
static DEVICE_ATTR(enable,S_IRUGO | S_IWUGO,
show_enable_value, store_enable_value );
static struct attribute *tsl4531_attributes[] = {
&dev_attr_lux_show.attr,
&dev_attr_enable.attr,
NULL
};
static const struct attribute_group tsl4531_attr_group = {
.attrs = tsl4531_attributes,
};
void tsl4531_callback_fun(struct work_struct *work)
{
struct tsl4531_data *chip = container_of(work,struct tsl4531_data,
pdata.work.work);
tsl4531_lux = chip->pdata.response[2];//Need to check on which response index we get lux value
input_report_abs(tsl4531_dev, ABS_X,tsl4531_lux);
input_sync(tsl4531_dev);
schedule_delayed_work(&chip->work, msecs_to_jiffies(1500));
}
static int __devinit tsl4531_probe(struct platform_device *pdev){
struct tsl4531_data *chip;
int err=0;
chip = kzalloc(sizeof(struct tsl4531_data), GFP_KERNEL);
if (!chip){
dev_dbg(&pdev->dev, "memory not allocated for tsl4531 light sensor module.\n");
return -ENOMEM;
}
dev_set_drvdata(&pdev->dev,chip);//here we give address in chip to struct device
tsl4531_dev=input_allocate_device();
if(!tsl4531_dev) {
dev_dbg(&pdev->dev, "memory not allocated for tsl4531_dev.\n");
return -ENOMEM;
}
err=input_register_device(tsl4531_dev);
if(err){
dev_dbg(&pdev->dev, "input register poll the device failed ... \n");
goto err_reg_poll;
}
mutex_init(&chip->update_lock);
err = sysfs_create_group(&pdev->dev.kobj,&tsl4531_attr_group);
if (err){
dev_dbg(&pdev->dev, "creating sysfs group for tsl4531 sensor module failed.\n");
goto exit_err;
}
INIT_DELAYED_WORK(&chip->work, tsl4531_polling_worker);
INIT_DELAYED_WORK(&chip->pdata.work,tsl4531_callback_fun);
chip->pdata.dev_id = DEVICE_LIGHT;
return 0;
return err;
}
static int __devexit tsl4531_remove(struct platform_device *pdev){
struct tsl4531_data *data = dev_get_drvdata(&pdev->dev);
cancel_delayed_work_sync(&data->work);
cancel_delayed_work(&data->pdata.work);
sysfs_remove_group(&pdev->dev.kobj, &tsl4531_attr_group);
unregister_sam4l_client(&data->pdata);
kfree(data);
return 0;
}
static const struct platform_device_id tsl4531_id[] = {
{ "tsl45317", 0 },
{ }
};
static struct platform_driver tsl4531_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "tsl45317",
},
.probe = tsl4531_probe,
.remove = tsl4531_remove,
.suspend = tsl4531_suspend,
.resume = tsl4531_resume,
.id_table = tsl4531_id,
};
static int __init tsl4531_init(void){
return platform_driver_register(&tsl4531_driver);
}
static void __exit tsl4531_exit(void){
platform_driver_unregister(&tsl4531_driver);
}
I have few doubts regarding working of container_of and dev_get_drvdata
1)in the polling_worker function we can see one container_of macro which fetches the address to the original structure and assigned to struct tsl4531_data *data;
2)in the probe function we can see one call to dev_set_drvdata and in store_enable_value and tsl4531 dev_get_drvdata.
Isn't both container_of and dev_set and dev_get doing same things here?
container_of and dev_set, dev_get are different. But yes, the intention might be the same. Both are actually used to retrieve the pointer (usually to the private data structure of the device).
container_of() actually does a reverse mapping. It does the opposite of &struct_base->member operation. In the previous operation you have the pointer to the base of the structure and need the address of one of its member. While, container_of takes in the address of the member and returns the base address. In the tsl4531_polling_worker() function, it has the member's address and using container_of it is getting the base address of the structure (struct tsl4531_data)
dev_set_drvdata() is generally used to preserve a pointer's address, such that it could be retrieved later using dev_get_drvdata(). Unlike reverse mapping, the functions stores and loads the address from a pointer of type void * (refer http://lxr.free-electrons.com/source/drivers/base/dd.c#L595)
Related
I made a static library in C language.
The functions of this library are as follows.
Save the callback function point in a global variable
The callback function has a parameter of the struct structure.
The library transmits struct data by calling the callback function to the library user at a specific moment.
The source for this is:
static library source
// ---------------------------------------------
// Static Library
// ---------------------------------------------
typedef struct
{
unsigned long m_Data1;
unsigned long m_Data2;
unsigned long m_Data3;
} SEND_DATA;
//
typedef int (*ReportCallbackProc)(SEND_DATA *pSendData);
//
static ReportCallbackProc gReportFunc = NULL;
static Period = 0;
// Set callback function pointer to gloval variable
int SetReport(ReportCallbackProc func, int period)
{
gReportFunc = func;
Period = period;
return(1);
}
// Send data to Application of library
void Report()
{
.............
SEND_DATA sendData;
sendData.m_Data1 = 1;
sendData.m_Data2 = 2;
sendData.m_Data3 = 3;
int rc = gReportFunc(&sendData);
if (rc != 1)
{
printf("gRealtimeReportFunc failed: status=[%d]\n", rc);
}
.....
}
application of this library
// ---------------------------------------------
// Application of Static Library
// ---------------------------------------------
void handle_report (SEND_DATA *pSendData)
{
printf("Report called");
printf("m_Data1 = %ld ", pSendData->m_Data1);
printf("m_Data2 = %ld ", pSendData->m_Data2);
printf("m_Data3 = %ld ", pSendData->m_Data3);
}
void main()
{
SetReport (&handle_report, period);
}
I want to make the above source in swift. Currently, I am trying to implement while studying swift.
However, it is not an easy problem and asks for help.
I tried creating and implementing closure usage and classes, but it was never easy.
Can you provide similar swift code?
Can you tell me how to implement it?
I've a Collection class which aims to store different kind of objects, however I'd like to call specific method name which these classes share (e.g. ToString()).
Here is my attempt:
class Collection {
public:
void *data[];
void Collection() {}
void ~Collection() {
for (int i = 0; i < ArraySize(data); i++) {
if (CheckPointer(data[i]) == POINTER_DYNAMIC) delete data[i];
}
}
void *Add(void *_object) {
uint _size = ArraySize(data);
ArrayResize(data, _size + 1, 100);
data[_size] = _object;
return _object;
}
string ToString(string _dlm = ",") {
string _out = "";
for (int i = 0; i < ArraySize(data); i++) {
if (CheckPointer(data[i]) == POINTER_DYNAMIC) {
_out += ((void *) data[i]).ToString(); // #fixme: Syntax error.
}
}
return _out;
}
};
However using ((void *) data[i]).ToString() syntax fails with:
'ToString' - member function not defined Collection.mqh
How can I call a ToString() method for each stored object?
It seems to me that it should be something like collection.toString() where collection is an object of your class Collection. Then each object that you add to your collection should implement this function... Maybe it is easier to mention some superclass that supports toString() (or interface with this method) and make sure that you add only correct objects? This also makes your code free of unexpected errors in runtime.
Also CArrayObj is at your disposal with most functions, if you need toString() or any other function then you can simply extend basic class. Maybe the only disadvantage of the default collection is that it stores CObject-inherited objects.
This can be achieved by creating an abstract class where all classes can share the same virtual method. For example:
class Object {
public:
virtual string ToString() = NULL;
};
class Foo : public Object {
public:
virtual string ToString() {
return "Foo";
};
};
class Bar : public Object {
public:
virtual string ToString() {
return "Bar";
};
};
Then in the Collection class the following method:
virtual string ToString(string _dlm = ",") {
string _out = "";
for (int i = 0; i < ArraySize(data); i++) {
if (CheckPointer(data[i]) == POINTER_DYNAMIC) {
_out += ((Object *) data[i]).ToString() + _dlm;
}
}
return _out;
}
Sample usage:
Collection *objects;
objects = new Collection;
Foo *foo = new Foo();
Bar *bar = new Bar();
objects.Add(foo);
objects.Add(bar);
Print(objects.ToString());
delete objects;
I'm getting access violation reading location when I try to set data of class object.
void make_heap_array()
{
//Example of ptr_arr is define: It's define in class variables: vector<shared_ptr<Data_Node<Item>>> ptr_arr;
int total_data = arr_data.size();
for (int i = 0; i < total_data; i++)
{
shared_ptr<Data_Node<Item>> new_node = shared_ptr<Data_Node<Item>>();
Item data = arr_data[i];
new_node->set_data(data); //Error: Access violation reading location
ptr_arr.push_back(new_node);
}
}
Data_Node is class using template with few methods and here is it's code:
template <class Item>
class Data_Node
{
Item info;
public:
const Item& data() const
{
return info;
}
void set_data(const Item& new_data)
{
info = new_data;
}
};
new_node is null (as you might well have checked yourself), so new_node->set_data(data) has undefined behaviour. (The default-constructed state of a shared pointer is null.)
Hello Everyone!!!
I am novice in Telephony Application and trying to make a very simple Panasonic telephone application to change class of service (COS) using Windows Tapi32.dll and panasonic TSP.I have made a function which will change the class of service in PBX ..But on running the application class of service is not changing in the PBX neither is my code giving me any type of error...Below is my code...
[DllImport("Tapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
internal static extern int lineDevSpecific(IntPtr hLine,uint dwAddressID,uint hCall, IntPtr lpParams,uint dwSize);
[StructLayout(LayoutKind.Sequential)]
public struct UserRec
{
public int dwMode
{
get
{
return dwMode;
}
set
{
dwMode = 4;
}
}
public int dwParam1
{
get
{
return dwParam1;
}
set
{
dwParam1 = 18;
}
}
}
public static void Main(string[] args)
{
uint add = 0;
uint call = 0;
uint size = 0;
string vline = "125";
//IntPtr hline = &vline;
IntPtr hline = Marshal.StringToHGlobalUni(vline);
var sizeUserRec = Marshal.SizeOf(typeof(UserRec));
var userRec = Marshal.AllocHGlobal(sizeUserRec);
lineDevSpecific(hline, add, call, userRec, size);
var x = (UserRec)Marshal.PtrToStructure(userRec, typeof(UserRec));
Marshal.FreeHGlobal(userRec);
Console.WriteLine("Hii");
}
Plz help me or direct me in the write direction to get the things done.Thanx in advance...
lineDevSpecific() exposes error conditions through its return value, not SetLastError(), so:
You probably should remove SetLastError=true from the [DllImport] attribute,
You should test the return value of the function against the error constants listed in the documentation:
int result = lineDevSpecific(hline, add, call, userRec, size);
if (result < 0) {
// Handle error, depending on the value of 'result'.
}
In GTK+, is it possible to access the GtkWidget -- text entry for file name in GtkFileChooser? I want to disable the editable attribute of the text entry using gtk_entry_set_editable.
As far as I know, no.
What do you ultimately want to achieve? Perhaps there is another approach.
If one had a legitimate reason to get a pointer to the GtkEntry, then derive from GtkFileChooserDialog, which will probably mutate into a GtkFileChooserDefault. GObject will complain about an illegal cast when checking type instance even though it works and the data of derived object can be accessed without errors, use GTK_FILE_CHOOSER instead of MY_FILE_CHOOSER to avoid the warning messages and a local static for the entry pointer. The entry widget is NOT accessible during construction. Here is the pertinent code:
static GtkEntry *chooser_entry;
static void my_file_chooser_finalize (GObject *object)
{
chooser_entry = NULL;
(G_OBJECT_CLASS (my_file_chooser_parent_class))->finalize (object);
}
static void my_file_chooser_init (MyFileChooser *self)
{
chooser_entry = NULL;
}
static void look_for_entry(GtkWidget *widget, void *self)
{
if (GTK_IS_ENTRY(widget)) {
chooser_entry = (GtkEntry*)widget;
}
else if (GTK_IS_CONTAINER(widget)) {
gtk_container_forall ( GTK_CONTAINER (widget), look_for_entry, self);
}
}
static void file_chooser_find_entry (GtkWidget *chooser)
{
GList *children, *iter;
/* Get all objects inside the dialog */
children = gtk_container_get_children (GTK_CONTAINER (chooser));
for (iter = children; iter; iter = iter->next) {
if (GTK_IS_CONTAINER(iter->data)) {
gtk_container_forall ( GTK_CONTAINER (iter->data), look_for_entry, chooser);
if (chooser_entry != NULL) {
break;
}
}
}
g_list_free (children);
}
GtkEntry *my_file_chooser_get_entry (GtkWidget *widget)
{
if (chooser_entry == NULL) {
file_chooser_find_entry (widget);
}
return chooser_entry;
}
char *my_file_chooser_get_entry_text(GtkWidget *widget)
{
char *text;
GtkEntry *entry;
text = NULL;
if (GTK_IS_FILE_CHOOSER(widget)) {
entry = my_file_chooser_get_entry(widget);
if (GTK_IS_ENTRY(entry)) {
if (gtk_entry_get_text_length (entry)) {
text = g_strdup (gtk_entry_get_text(entry));
}
}
}
return text;
}
Maybe not ideal, but works.