gaston
gaston

Reputation: 425

Linux Kernel Module : Problem with kernel_write function

I have a problem using kernel_write function while I am developing LKM for Linux 4.14.73 version.

This is the part of my module where I am facing the issue :

void change_led_state(char *led_path, int led_value)
{


    printk("we are in change_led_state\n");
    size_t len = sizeof(led_value);
    char    lpath[64];
    ssize_t rk=0;

    strncpy(lpath, led_path, sizeof(lpath) - 1);
    lpath[sizeof(lpath) - 1] = '\0';
    f_led = filp_open(lpath, O_WRONLY , 0);

    if (f_led == NULL) {
        printk("Unable to access led\n");
        return;
    }


    rk = kernel_write(f_led, led_value, len, &f_led->f_pos);
    printk("rk = %d\n", rk);
    filp_close(f_led, NULL);
}

rk is usually getting a negative value. I think it must be positive. What's wrong with the function please ? How can I correct it ?

For more informations, I have the same code but in user-space program, and it's working fine, I just want to replace it to kernel space. This is the user space program :

void change_led_state(char *led_path, int led_value)
{
    char    lpath[64];
    FILE    *led_fd;

    strncpy(lpath, led_path, sizeof(lpath) - 1);
    lpath[sizeof(lpath) - 1] = '\0';

    led_fd = fopen(lpath, "w");

    if (led_fd == NULL) {
        fprintf(stderr, "simplekey: unable to access led\n");
        return;
    }

    fprintf(led_fd, "%d\n", led_value);

    fclose(led_fd);
}


void reset_leds(void)
{
    change_led_state(LED_PATH "/" green "/brightness", 0);
}

void eval_keycode(int code)
{
    static int green_state = 0;

    switch (code) {
    case 260:
        printf("BTN pressed\n");

        // figure out red state
        green_state = green_state ? 0 : 1;

        change_led_state(LED_PATH "/" green "/brightness", green_state);
        break;

    default :
        printf("Wrong Button was pressed\n");
        break;
    }
}

In the main fuction I just call eval_keycode function and it's working. What mistakes I have made ?

Upvotes: 0

Views: 2922

Answers (1)

Ian Abbott
Ian Abbott

Reputation: 17403

In your call:

    rk = kernel_write(f_led, led_value, len, &f_led->f_pos);

The second parameter is supposed to be a char *, but you are passing an int.

In addition, when writing to the "/sys/class/leds/[device]/brightness" file, the code that handles this expects a pointer to a string of decimal digits, terminated by some non-digit character (such as a newline) or a null terminator.

You need to "print" your led_value to a char array as a decimal number and write the array contents to the file:

    char led_valstr[20]; /* should be large enough */

    len = scnprintf(led_valstr, sizeof(led_valstr), "%d\n", led_value);
    rk = kernel_write(f_led, led_valstr, len, &f_led->f_pos);

(EDIT: corrected call to scnprintf.)

Upvotes: 1

Related Questions