Warning from gcc: braces around scalar initializer, how to fix? - c

At rewriting kernel driver I got this warning:
msm-cirrus-playback.c:545:2: warning: braces around scalar initializer
Read that this warning appears when I am declaring one structure's field in {}:
struct random_struct test = {
{ .name = "StackOverflow" },
{ .name = "StackExchange" },
};
But my structure have 2-3 fields in {}:
static struct device_attribute *opalum_dev_attr = {
{
.attr->name = "temp-acc",
.show = opsl_temp_acc_show,
.store = opsl_temp_acc_store,
},
{
.attr->name = "count",
.show = opsl_count_show,
.store = opsl_count_store,
},
{
.attr->name = "ambient",
.show = opsl_ambient_show,
.store = opsl_ambient_store,
},
{
.attr->name = "f0",
.show = opsl_f0_show,
.store = opsl_f0_store,
},
{
.attr->name = "pass",
.show = opsl_pass_show,
},
{
.attr->name = "start",
.show = opsl_cali_start,
},
};
This structure:
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
How can I fix this warning? Qualcomm kernels are building with -Werror flag, so this warning is critical.

static struct device_attribute *opalum_dev_attr means declare opalum_dev_attr as static pointer to struct device_attribute
Your code is trying to initialize a static array of struct device_attribute
What you want is: static struct device_attribute opalum_dev_attr[] which means declare opalum_dev_attr as static array of struct device_attribute

It is because you initialize the pointer to the struct not the struct itself.
you need to assign the reference to the struct for example by using compound literals
struct x
{
int a,b,c;
}a = {1,2,3};
void foo()
{
struct x a = {1,2,3};
struct x *b = {1,2,3}; // wrong warning here
struct x *x = &(struct x){1,2,3}; // correct reference to the struct assigned (using compound literal
struct x *y = (struct x[]){{1,2,3}, {4,5,6}, {4,5,6}, };
struct x z[] = {{1,2,3}, {4,5,6}, {4,5,6}, };
}

Related

Linux USB Driver: "Unknown symbol in module" with insmod

I'm currently learning how to create USB drivers for Linux, and I absolutely love it so far! However, I've come across an issue when trying to insert my .ko file. I keep receiving the following error: "Unknown symbol in module".
Below, you will find my code. What is weird is if I comment out the code in my __init function, the module loads just fine, however after going through my code, and comparing it to other USB driver code, I am unable to locate any issues. Could you please help me out? Thanks so much for your help
struct xb1_controller {
struct usb_device *udev;
struct usb_interface *interface;
unsigned char minor;
char *int_in_buffer;
struct usb_endpoint_descriptor *endpoint;
struct urb *int_in_urb;
};
static struct usb_device_id xb1_table [] = {
{USB_DEVICE(xb1_vendor_id, xb1_product_id) },
{}
};
MODULE_DEVICE_TABLE(usb, xb1_table);
static int xb1_open(struct inode *inode, struct file *file) {
//Sys call
}
static int xb1_release(struct inode *inode, struct file *file) {
//Sys call
}
static ssize_t xb1_read(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos) {
//Sys call
}
static struct file_operations xb1_fops = {
.owner = THIS_MODULE,
.open = xb1_open,
.release = xb1_release,
.read = xb1_read,
};
static struct usb_class_driver xb1_class = {
.name = "xb1driver",
.fops = &xb1_fops,
.minor_base = MINOR_BASE,
};
static int xb1_probe(struct usb_interface *interface, const struct
usb_device_id *id) {
printk(KERN_INFO "xb1driver probe function called");
}
static void xb1_disconnect(struct usb_interface *interface) {
printk(KERN_INFO "xb1driver disconnect function called");
}
static struct usb_driver xb1_driver = {
.name = "xb1driver",
.id_table = xb1_table,
.probe = xb1_probe,
.disconnect = xb1_disconnect,
};
static int __init xb1_init(void) {
int result;
result = usb_register(&xb1_driver);
if(result) {
printk(KERN_INFO "usb_register has failed..");
return 5;
}
return result;
}
static void __exit xb1_exit(void) {
usb_deregister(&xb1_driver);
}
module_init(xb1_init);
module_exit(xb1_exit);

How to call `struct dev_archdata' function?

I have found a lot of questions with this error (initializer element is not constant) but I don't know how to adapt the answers in my code.
(I'm new in C)
I have an error with this part:
#include <mach/i2c.h>
#include <mach/irqs-sun7i.h>
/*
* /////////// from mach/i2c.h //////////
struct sun7i_i2c_platform_data {
int bus_num;
unsigned int frequency;
};
*/
static struct sun7i_i2c_platform_data sun7i_i2c_platform_data = {
.bus_num = 1,
.frequency = 100*1000,
};
static struct mpu_platform_data gyro_platform_data = {
.int_config = 0x10,
.level_shifter = 0,
.orientation = { -1, 0, 0,
0, 1, 0,
0, 0, -1 },
.sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
.sec_slave_id = COMPASS_ID_AK8972,
.secondary_i2c_addr = 0x0E
};
/*
* /////////// from mach/i2c.h //////////
*
* struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;
int irq;
};*/
static struct i2c_board_info __initdata sun7i_i2c_platform_device[] = {
{
I2C_BOARD_INFO("mpu6050", 0x68),
.platform_data = &gyro_platform_data,
.archdata = sun7i_i2c_platform_data,
},
};
/*
// ORIGINAL //
static struct i2c_board_info __initdata single_chip_board_info[] = {
{
I2C_BOARD_INFO("mpu6050", 0x68),
.irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
.platform_data = &gyro_platform_data,
},
};
*/
static void __init sun7i_i2c_init(void)
{
i2c_register_board_info(2, sun7i_i2c_platform_device,
ARRAY_SIZE(sun7i_i2c_platform_device));
}
My problem come from .archdata init:
c:160:17: error: initializer element is not constant
I have tried with
.archdata = &sun7i_i2c_platform_data,
but in this case I have a warning and the line is ignored:
warning: initialization from incompatible pointer type [enabled by default]
So, how to call properly my fonction ?
Thanks

Proper way to initialize a const member of dynamically allocated struct

I have these 2 structs:
struct Params {
int a;
int b;
};
struct Foo {
const struct Params settings;
int state;
};
The settings member is const as a hint that it should not be changed once a struct Foo has been created and initialized.
And I want to dynamically allocate this struct, e.g.
struct Foo * new_foo(void)
{
struct Foo *n = malloc(sizeof *n);
if (n) {
n->settings.a = SETTING_A;
n->settings.b = SETTING_B;
...
}
return n;
}
Now, this will not compile due to settings being const. What is a proper way to
initialize such a struct in this manner? Or is it better to not declare the settings member as const?
The memory is allocated (and thus, not constant), so it is legal to cast const away:
struct Foo * new_foo(void)
{
struct Foo *n = malloc(sizeof *n);
if (n) {
struct Params *s = (void *)&n->settings;
s->a = SETTING_A;
s->b = SETTING_B;
}
return n;
}
Here is one way to do it:
struct Foo *new_foo(void)
{
static struct Foo foo =
{
.settings =
{
.a = SETTING_A,
.b = SETTING_B
},
.state = ...
};
struct Foo *n = malloc(sizeof *n);
memcpy(n, &foo, sizeof *n);
return n;
}
Here is another way to do it:
struct Foo *new_foo(void)
{
static struct Params settings =
{
.a = SETTING_A,
.b = SETTING_B
};
struct Foo *n = malloc(sizeof *n);
memcpy((struct Params*)&n->settings, &settings, sizeof settings);
n->state = ...;
return n;
}

Initialize sized, static string lists in C

I want to create string lists with a discoverable size and am not sure if I have the right method/syntax. Here is my attempt:
typedef struct {
unsigned int size;
char** list;
} STRLIST;
static STRLIST listMediaType = {
.size = 7,
.list = {
"Book",
"Map",
"Booklet",
"Pamphlet",
"Magazine",
"Report",
"Journal"
},
};
Is this the right approach? Note that I do not want to hardcode the size into the structure because I want to use the same type to define many different lists. For example, imagine the following function:
void printList( STRLIST* pList ){
for( int x = 0; x < pList->size; x++ ) printf( "%s\n", pList->list );
}
It can be done with C99 compound-literals and a slight change:
http://coliru.stacked-crooked.com/a/4497d2645ad21b74
typedef struct STRLIST{
unsigned int size;
char** list;
} STRLIST;
static STRLIST listMediaType = {
.size = 7,
.list = (char*[]){
"Book",
"Map",
"Booklet",
"Pamphlet",
"Magazine",
"Report",
"Journal"
},
};
Alternative for C90 (thus without compound-literals and designated initializers): http://coliru.stacked-crooked.com/a/5cc95d25afc18c91
static char* list[] = {
"Book",
"Map",
"Booklet",
"Pamphlet",
"Magazine",
"Report",
"Journal"
};
static STRLIST listMediaType = {
sizeof list / sizeof *list,
// Used sizeof to avoid manually typing the lists length
list,
};
As an aside, an array with a sentinel-NULL is far simpler than a counted array.
Does not even need a new type.
static char* list[] = {
"Book",
"Map",
"Booklet",
"Pamphlet",
"Magazine",
"Report",
"Journal",
0
};
void printList(char** pList){
while(*pList) printf( "%s\n", *pList++);
}
You may check this code:
#include <stdio.h>
typedef struct {
unsigned int size;
char* list[];
} STRLIST;
static STRLIST listMediaType = {
7,
{
"Book",
"Map",
"Booklet",
"Pamphlet",
"Magazine",
"Report",
"Journal"
}
};
int main() {
printf("struct size: %d\n", listMediaType.size);
int i;
for (i = 0; i < listMediaType.size; i++)
printf("struct elem[%d] = \"%s\"\n",
i,
listMediaType.list[i]);
return 0;
}
I think there are 2 problems in your approach:
Is TYPEDEF syntactic correct in C? I think you should write it in lowercase.
If you want to initialize a struct, just use the brace and without .attributes
Hope this one will help.
Thanks

How do I assign value when structure has a void *pointer

I am trying to assign a value to variable which has a void *pointer. Below is the assignment as best as I understand. (Doesn't work)
void set_fb_video ()
{
goldfish_lcd.dev.(atmel_lcdfb_info*)platform_data->default_monspecs->modedb->xres = 10;
};
Below are part of structures as defined in header files
Header files
struct fb_videomode {
..
u32 xres;
..
};
struct fb_monspecs {
..
struct fb_videomode *modedb;
..
};
struct atmel_lcdfb_info;
struct atmel_lcdfb_info {
..
struct fb_monspecs *default_monspecs;
..
};
struct device {
..
void *platform_data;
..
};
struct platform_device {
..
struct device dev;
..
};
C files
struct fb_videomode at91_tft_vga_modes[] = {
..
.xres = 100,
..
};
struct fb_monspecs &at91fb_default_monspecs = {
..
.modedb = at91_tft_vga_modes,
..
};
struct atmel_lcdfb_info ek_lcdc_data = {
..
.default_monspecs = &at91fb_default_monspecs,
..
};
struct platform_device goldfish_lcd ={
..
.dev = {
..
.platform_data = &ek_lcdc_data,
},
..
};
Any suggestions are greatly appreciated.
Thank you in advance
Your cast isn't in the correct place, and you don't have a type called atmel_lcdfb_info:
((struct atmel_lcdfb_info*)goldfish_lcd.dev.platform_data)->default_monspecs->modedb->xres = 10;

Resources