From 995c5b3c635760f63795927507a6cbff32d25f7b Mon Sep 17 00:00:00 2001 From: nirenjan Date: Mon, 30 Nov 2015 20:11:18 -0800 Subject: [PATCH] Breakout functionality into individual files --- libx52/{x52control.h => x52_commands.h} | 6 +- libx52/x52_control.c | 197 ++++++++++ libx52/{x52core.c => x52_core.c} | 2 +- libx52/x52_date_time.c | 129 +++++++ libx52/x52_mfd_led.c | 150 ++++++++ libx52/x52control.c | 456 ------------------------ 6 files changed, 480 insertions(+), 460 deletions(-) rename libx52/{x52control.h => x52_commands.h} (93%) create mode 100644 libx52/x52_control.c rename libx52/{x52core.c => x52_core.c} (98%) create mode 100644 libx52/x52_date_time.c create mode 100644 libx52/x52_mfd_led.c delete mode 100644 libx52/x52control.c diff --git a/libx52/x52control.h b/libx52/x52_commands.h similarity index 93% rename from libx52/x52control.h rename to libx52/x52_commands.h index 45adec8..ecb6b1a 100644 --- a/libx52/x52control.h +++ b/libx52/x52_commands.h @@ -9,8 +9,8 @@ * */ -#ifndef X52JOY_COMMANDS_H -#define X52JOY_COMMANDS_H +#ifndef X52_COMMANDS_H +#define X52_COMMANDS_H /* X52 vendor API commands */ /* Vendor request - all commands must have this request ID */ @@ -50,4 +50,4 @@ #define X52_BLINK_ON 0x51 #define X52_BLINK_OFF 0x50 -#endif /* !defined X52JOY_COMMANDS_H */ +#endif /* !defined X52_COMMANDS_H */ diff --git a/libx52/x52_control.c b/libx52/x52_control.c new file mode 100644 index 0000000..b9e9a54 --- /dev/null +++ b/libx52/x52_control.c @@ -0,0 +1,197 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include "libx52.h" +#include "x52_commands.h" +#include "x52_common.h" + +static int libx52_control_transfer(libx52_device *x52, uint16_t index, uint16_t value) +{ + return libusb_control_transfer(x52->hdl, + LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + X52_VENDOR_REQUEST, value, index, NULL, 0, 1000); +} + +static int libx52_write_line(libx52_device *x52, uint8_t line_index) +{ + uint8_t i; + uint16_t value; + int rc; + + const uint16_t line_index_map[X52_MFD_LINES] = { + X52_MFD_LINE1, + X52_MFD_LINE2, + X52_MFD_LINE3, + }; + + /* Clear the line first */ + rc = libx52_control_transfer(x52, + line_index_map[line_index] | X52_MFD_CLEAR_LINE, 0); + if (rc) { + return rc; + } + + for (i = 0; i < x52->line[line_index].length; i += 2) { + value = x52->line[line_index].text[i + 1] << 8 | + x52->line[line_index].text[i]; + + rc = libx52_control_transfer(x52, + line_index_map[line_index] | X52_MFD_WRITE_LINE, value); + if (rc) { + return rc; + } + } + + return rc; +} + +static int libx52_write_date(libx52_device *x52) +{ + uint16_t value1; //dd-mm + uint16_t value2; //yy + int rc; + + switch (x52->date_format) { + case LIBX52_DATE_FORMAT_YYMMDD: + value1 = x52->date_month << 8 | + x52->date_year; + value2 = x52->date_day; + break; + + case LIBX52_DATE_FORMAT_MMDDYY: + value1 = x52->date_day << 8 | + x52->date_month; + value2 = x52->date_year; + break; + + case LIBX52_DATE_FORMAT_DDMMYY: + value1 = x52->date_month << 8 | + x52->date_day; + value2 = x52->date_year; + break; + + default: + return -EINVAL; + } + + rc = libx52_control_transfer(x52, X52_DATE_DDMM, value1); + if (rc == 0) { + rc = libx52_control_transfer(x52, X52_DATE_YEAR, value2); + } + + return rc; +} + +int libx52_update(libx52_device *x52) +{ + unsigned int i; + uint32_t update_mask; + uint16_t value; + int rc; + + /* Save the update mask */ + update_mask = x52->update_mask; + /* Reset the device update mask to 0 */ + x52->update_mask = 0; + + for (i = 0; i < 32; i++) { + if (tst_bit(&update_mask, i)) { + switch (i) { + case X52_BIT_SHIFT: + value = tst_bit(&x52->led_mask, X52_BIT_SHIFT) ? X52_SHIFT_ON : X52_SHIFT_OFF; + rc = libx52_control_transfer(x52, X52_SHIFT_INDICATOR, value); + break; + + case X52_BIT_LED_FIRE: + case X52_BIT_LED_A_RED: + case X52_BIT_LED_A_GREEN: + case X52_BIT_LED_B_RED: + case X52_BIT_LED_B_GREEN: + case X52_BIT_LED_D_RED: + case X52_BIT_LED_D_GREEN: + case X52_BIT_LED_E_RED: + case X52_BIT_LED_E_GREEN: + case X52_BIT_LED_T1_RED: + case X52_BIT_LED_T1_GREEN: + case X52_BIT_LED_T2_RED: + case X52_BIT_LED_T2_GREEN: + case X52_BIT_LED_T3_RED: + case X52_BIT_LED_T3_GREEN: + case X52_BIT_LED_POV_RED: + case X52_BIT_LED_POV_GREEN: + case X52_BIT_LED_I_RED: + case X52_BIT_LED_I_GREEN: + case X52_BIT_LED_THROTTLE: + /* The bits correspond exactly to the LED identifiers */ + value = tst_bit(&x52->led_mask, i) ? 1 : 0; + rc = libx52_control_transfer(x52, X52_LED, value | (i << 8)); + break; + + case X52_BIT_MFD_LINE1: + rc = libx52_write_line(x52, 0); + break; + + case X52_BIT_MFD_LINE2: + rc = libx52_write_line(x52, 1); + break; + + case X52_BIT_MFD_LINE3: + rc = libx52_write_line(x52, 2); + break; + + case X52_BIT_POV_BLINK: + value = tst_bit(&x52->led_mask, X52_BIT_POV_BLINK) ? X52_BLINK_ON : X52_BLINK_OFF; + rc = libx52_control_transfer(x52, X52_BLINK_INDICATOR, value); + break; + + case X52_BIT_BRI_MFD: + rc = libx52_control_transfer(x52, X52_MFD_BRIGHTNESS, + x52->mfd_brightness); + break; + + case X52_BIT_BRI_LED: + rc = libx52_control_transfer(x52, X52_LED_BRIGHTNESS, + x52->led_brightness); + break; + + case X52_BIT_MFD_DATE: + rc = libx52_write_date(x52); + break; + + case X52_BIT_MFD_TIME: + case X52_BIT_MFD_OFFS1: + case X52_BIT_MFD_OFFS2: + default: + /* Ignore any spurious bits */ + rc = 0; + break; + } + + if (rc == 0) { + clr_bit(&update_mask, i); + } else { + /* Last transfer failed - reset the update mask */ + x52->update_mask = update_mask; + break; + } + } + } + + return rc; +} diff --git a/libx52/x52core.c b/libx52/x52_core.c similarity index 98% rename from libx52/x52core.c rename to libx52/x52_core.c index 93d5fe1..9828955 100644 --- a/libx52/x52core.c +++ b/libx52/x52_core.c @@ -18,7 +18,7 @@ #include #include "libx52.h" -#include "x52control.h" +#include "x52_commands.h" #include "x52_common.h" #define VENDOR_SAITEK 0x06a3 diff --git a/libx52/x52_date_time.c b/libx52/x52_date_time.c new file mode 100644 index 0000000..6de9817 --- /dev/null +++ b/libx52/x52_date_time.c @@ -0,0 +1,129 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include "libx52.h" +#include "x52_commands.h" +#include "x52_common.h" + +int libx52_set_clock(libx52_device *x52, time_t time, int local) +{ + struct tm timeval; + if (!x52) { + return -EINVAL; + } + + if (local) { + timeval = *localtime(&time); + /* timezone from time.h presents the offset in seconds west of GMT. + * Negate and divide by 60 to get the offset in minutes east of GMT. + */ + x52->timezone[LIBX52_CLOCK_1] = -timezone / 60; + } else { + timeval = *gmtime(&time); + /* No offset from GMT */ + x52->timezone[LIBX52_CLOCK_1] = 0; + } + + x52->date_day = timeval.tm_mday; + x52->date_month = timeval.tm_mon + 1; + x52->date_year = timeval.tm_year % 100; + x52->time_hour = timeval.tm_hour; + x52->time_minute = timeval.tm_min; + + set_bit(&x52->update_mask, X52_BIT_MFD_DATE); + set_bit(&x52->update_mask, X52_BIT_MFD_TIME); + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); + return 0; +} + +int libx52_set_clock_timezone(libx52_device *x52, libx52_clock_id clock, int offset) +{ + if (!x52) { + return -EINVAL; + } + + /* Limit offset to +/- 24 hours */ + if (offset < -1440 || offset > 1440) { + return -EDOM; + } + + switch (clock) { + case LIBX52_CLOCK_2: + x52->timezone[clock] = offset; + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); + break; + + case LIBX52_CLOCK_3: + x52->timezone[clock] = offset; + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); + break; + + default: + return -ENOTSUP; + } + + return 0; +} + +int libx52_set_clock_format(libx52_device *x52, + libx52_clock_id clock, + libx52_clock_format format) +{ + if (!x52) { + return -EINVAL; + } + + if ((format != LIBX52_CLOCK_FORMAT_12HR) && + (format != LIBX52_CLOCK_FORMAT_24HR)) { + + return -EINVAL; + } + + switch (clock) { + case LIBX52_CLOCK_1: + set_bit(&x52->update_mask, X52_BIT_MFD_TIME); + break; + + case LIBX52_CLOCK_2: + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); + break; + + case LIBX52_CLOCK_3: + set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); + break; + + default: + return -EINVAL; + } + + x52->time_format[clock] = format; + return 0; +} + +int libx52_set_date_format(libx52_device *x52, libx52_date_format format) +{ + if (!x52) { + return -EINVAL; + } + + x52->date_format = format; + set_bit(&x52->update_mask, X52_BIT_MFD_DATE); + return 0; +} diff --git a/libx52/x52_mfd_led.c b/libx52/x52_mfd_led.c new file mode 100644 index 0000000..598e6d0 --- /dev/null +++ b/libx52/x52_mfd_led.c @@ -0,0 +1,150 @@ +/* + * Saitek X52 Pro MFD & LED driver + * + * Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + */ + +#include +#include +#include +#include +#include + +#include "x52_common.h" + +int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t length) +{ + if (!x52 || !text) { + return -EINVAL; + } + + if (line > 2) { + return -EINVAL; + } + + if (length > X52_MFD_LINE_SIZE) { + length = X52_MFD_LINE_SIZE; + } + + memset(x52->line[line].text, ' ', X52_MFD_LINE_SIZE); + memcpy(x52->line[line].text, text, length); + x52->line[line].length = length; + set_bit(&x52->update_mask, X52_BIT_MFD_LINE1 + line); + + return 0; +} + +int libx52_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state state) +{ + if (!x52) { + return -EINVAL; + } + + switch (led) { + case LIBX52_LED_FIRE: + case LIBX52_LED_THROTTLE: + if (state == LIBX52_LED_STATE_OFF) { + clr_bit(&x52->led_mask, led); + set_bit(&x52->update_mask, led); + } else if (state == LIBX52_LED_STATE_ON) { + set_bit(&x52->led_mask, led); + set_bit(&x52->update_mask, led); + } else { + /* Colors not supported */ + return -ENOTSUP; + } + break; + + default: + /* All other LEDs support OFF, RED, AMBER and GREEN states + * However, they are composed of individual RED and GREEN LEDs which + * must be turned on or off individually. + */ + switch (state) { + case LIBX52_LED_STATE_OFF: + clr_bit(&x52->led_mask, led + 0); // Red + clr_bit(&x52->led_mask, led + 1); // Green + break; + + case LIBX52_LED_STATE_RED: + set_bit(&x52->led_mask, led + 0); // Red + clr_bit(&x52->led_mask, led + 1); // Green + break; + + case LIBX52_LED_STATE_AMBER: + set_bit(&x52->led_mask, led + 0); // Red + set_bit(&x52->led_mask, led + 1); // Green + break; + + case LIBX52_LED_STATE_GREEN: + clr_bit(&x52->led_mask, led + 0); // Red + set_bit(&x52->led_mask, led + 1); // Green + break; + + default: + /* Cannot set the LED to "ON" */ + return -ENOTSUP; + } + + /* Set the update mask bits */ + set_bit(&x52->update_mask, led + 0); // Red + set_bit(&x52->update_mask, led + 1); // Green + break; + } + + return 0; +} + +int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness) +{ + if (!x52) { + return -EINVAL; + } + + if (mfd) { + x52->mfd_brightness = brightness; + set_bit(&x52->update_mask, X52_BIT_BRI_MFD); + } else { + x52->led_brightness = brightness; + set_bit(&x52->update_mask, X52_BIT_BRI_LED); + } + + return 0; +} + +int libx52_set_shift(libx52_device *x52, uint8_t state) +{ + if (!x52) { + return -EINVAL; + } + + if (state) { + set_bit(&x52->led_mask, X52_BIT_SHIFT); + } else { + clr_bit(&x52->led_mask, X52_BIT_SHIFT); + } + + set_bit(&x52->update_mask, X52_BIT_SHIFT); + return 0; +} + +int libx52_set_blink(libx52_device *x52, uint8_t state) +{ + if (!x52) { + return -EINVAL; + } + + if (state) { + set_bit(&x52->led_mask, X52_BIT_POV_BLINK); + } else { + clr_bit(&x52->led_mask, X52_BIT_POV_BLINK); + } + + set_bit(&x52->update_mask, X52_BIT_POV_BLINK); + return 0; +} diff --git a/libx52/x52control.c b/libx52/x52control.c deleted file mode 100644 index 81421d0..0000000 --- a/libx52/x52control.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Saitek X52 Pro MFD & LED driver - * - * Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include "libx52.h" -#include "x52control.h" -#include "x52_common.h" - -static int libx52_control_transfer(libx52_device *x52, uint16_t index, uint16_t value) -{ - return libusb_control_transfer(x52->hdl, - LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, - X52_VENDOR_REQUEST, value, index, NULL, 0, 1000); -} - -static int libx52_write_line(libx52_device *x52, uint8_t line_index) -{ - uint8_t i; - uint16_t value; - int rc; - - const uint16_t line_index_map[X52_MFD_LINES] = { - X52_MFD_LINE1, - X52_MFD_LINE2, - X52_MFD_LINE3, - }; - - /* Clear the line first */ - rc = libx52_control_transfer(x52, - line_index_map[line_index] | X52_MFD_CLEAR_LINE, 0); - if (rc) { - return rc; - } - - for (i = 0; i < x52->line[line_index].length; i += 2) { - value = x52->line[line_index].text[i + 1] << 8 | - x52->line[line_index].text[i]; - - rc = libx52_control_transfer(x52, - line_index_map[line_index] | X52_MFD_WRITE_LINE, value); - if (rc) { - return rc; - } - } - - return rc; -} - -int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t length) -{ - if (!x52 || !text) { - return -EINVAL; - } - - if (line > 2) { - return -EINVAL; - } - - if (length > X52_MFD_LINE_SIZE) { - length = X52_MFD_LINE_SIZE; - } - - memset(x52->line[line].text, ' ', X52_MFD_LINE_SIZE); - memcpy(x52->line[line].text, text, length); - x52->line[line].length = length; - set_bit(&x52->update_mask, X52_BIT_MFD_LINE1 + line); - - return 0; -} - -int libx52_set_led(libx52_device *x52, uint8_t led, uint8_t state) -{ - if (!x52) { - return -EINVAL; - } - - if (led > X52_BIT_LED_THROTTLE || led < X52_BIT_LED_FIRE) { - return -EINVAL; - } - - if (state) { - set_bit(&x52->led_mask, led); - } else { - clr_bit(&x52->led_mask, led); - } - - set_bit(&x52->update_mask, led); - return 0; -} - -int libx52_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state state) -{ - if (!x52) { - return -EINVAL; - } - - switch (led) { - case LIBX52_LED_FIRE: - case LIBX52_LED_THROTTLE: - if (state == LIBX52_LED_STATE_OFF) { - clr_bit(&x52->led_mask, led); - set_bit(&x52->update_mask, led); - } else if (state == LIBX52_LED_STATE_ON) { - set_bit(&x52->led_mask, led); - set_bit(&x52->update_mask, led); - } else { - /* Colors not supported */ - return -ENOTSUP; - } - break; - - default: - /* All other LEDs support OFF, RED, AMBER and GREEN states - * However, they are composed of individual RED and GREEN LEDs which - * must be turned on or off individually. - */ - switch (state) { - case LIBX52_LED_STATE_OFF: - clr_bit(&x52->led_mask, led + 0); // Red - clr_bit(&x52->led_mask, led + 1); // Green - break; - - case LIBX52_LED_STATE_RED: - set_bit(&x52->led_mask, led + 0); // Red - clr_bit(&x52->led_mask, led + 1); // Green - break; - - case LIBX52_LED_STATE_AMBER: - set_bit(&x52->led_mask, led + 0); // Red - set_bit(&x52->led_mask, led + 1); // Green - break; - - case LIBX52_LED_STATE_GREEN: - clr_bit(&x52->led_mask, led + 0); // Red - set_bit(&x52->led_mask, led + 1); // Green - break; - - default: - /* Cannot set the LED to "ON" */ - return -ENOTSUP; - } - - /* Set the update mask bits */ - set_bit(&x52->update_mask, led + 0); // Red - set_bit(&x52->update_mask, led + 1); // Green - break; - } - - return 0; -} - -static int libx52_write_date(libx52_device *x52) -{ - uint16_t value1; //dd-mm - uint16_t value2; //yy - int rc; - - switch (x52->date_format) { - case LIBX52_DATE_FORMAT_YYMMDD: - value1 = x52->date_month << 8 | - x52->date_year; - value2 = x52->date_day; - break; - - case LIBX52_DATE_FORMAT_MMDDYY: - value1 = x52->date_day << 8 | - x52->date_month; - value2 = x52->date_year; - break; - - case LIBX52_DATE_FORMAT_DDMMYY: - value1 = x52->date_month << 8 | - x52->date_day; - value2 = x52->date_year; - break; - - default: - return -EINVAL; - } - - rc = libx52_control_transfer(x52, X52_DATE_DDMM, value1); - if (rc == 0) { - rc = libx52_control_transfer(x52, X52_DATE_YEAR, value2); - } - - return rc; -} - -int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness) -{ - if (!x52) { - return -EINVAL; - } - - if (mfd) { - x52->mfd_brightness = brightness; - set_bit(&x52->update_mask, X52_BIT_BRI_MFD); - } else { - x52->led_brightness = brightness; - set_bit(&x52->update_mask, X52_BIT_BRI_LED); - } - - return 0; -} - -int libx52_set_shift(libx52_device *x52, uint8_t state) -{ - if (!x52) { - return -EINVAL; - } - - if (state) { - set_bit(&x52->led_mask, X52_BIT_SHIFT); - } else { - clr_bit(&x52->led_mask, X52_BIT_SHIFT); - } - - set_bit(&x52->update_mask, X52_BIT_SHIFT); - return 0; -} - -int libx52_set_blink(libx52_device *x52, uint8_t state) -{ - if (!x52) { - return -EINVAL; - } - - if (state) { - set_bit(&x52->led_mask, X52_BIT_POV_BLINK); - } else { - clr_bit(&x52->led_mask, X52_BIT_POV_BLINK); - } - - set_bit(&x52->update_mask, X52_BIT_POV_BLINK); - return 0; -} - -int libx52_set_clock(libx52_device *x52, time_t time, int local) -{ - struct tm timeval; - if (!x52) { - return -EINVAL; - } - - if (local) { - timeval = *localtime(&time); - /* timezone from time.h presents the offset in seconds west of GMT. - * Negate and divide by 60 to get the offset in minutes east of GMT. - */ - x52->timezone[LIBX52_CLOCK_1] = -timezone / 60; - } else { - timeval = *gmtime(&time); - /* No offset from GMT */ - x52->timezone[LIBX52_CLOCK_1] = 0; - } - - x52->date_day = timeval.tm_mday; - x52->date_month = timeval.tm_mon + 1; - x52->date_year = timeval.tm_year % 100; - x52->time_hour = timeval.tm_hour; - x52->time_minute = timeval.tm_min; - - set_bit(&x52->update_mask, X52_BIT_MFD_DATE); - set_bit(&x52->update_mask, X52_BIT_MFD_TIME); - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); - return 0; -} - -int libx52_set_clock_timezone(libx52_device *x52, libx52_clock_id clock, int offset) -{ - if (!x52) { - return -EINVAL; - } - - /* Limit offset to +/- 24 hours */ - if (offset < -1440 || offset > 1440) { - return -EDOM; - } - - switch (clock) { - case LIBX52_CLOCK_2: - x52->timezone[clock] = offset; - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); - break; - - case LIBX52_CLOCK_3: - x52->timezone[clock] = offset; - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); - break; - - default: - return -ENOTSUP; - } - - return 0; -} - -int libx52_set_clock_format(libx52_device *x52, - libx52_clock_id clock, - libx52_clock_format format) -{ - if (!x52) { - return -EINVAL; - } - - if ((format != LIBX52_CLOCK_FORMAT_12HR) && - (format != LIBX52_CLOCK_FORMAT_24HR)) { - - return -EINVAL; - } - - switch (clock) { - case LIBX52_CLOCK_1: - set_bit(&x52->update_mask, X52_BIT_MFD_TIME); - break; - - case LIBX52_CLOCK_2: - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS1); - break; - - case LIBX52_CLOCK_3: - set_bit(&x52->update_mask, X52_BIT_MFD_OFFS2); - break; - - default: - return -EINVAL; - } - - x52->time_format[clock] = format; - return 0; -} - -int libx52_set_date_format(libx52_device *x52, libx52_date_format format) -{ - if (!x52) { - return -EINVAL; - } - - x52->date_format = format; - set_bit(&x52->update_mask, X52_BIT_MFD_DATE); - return 0; -} - -int libx52_update(libx52_device *x52) -{ - unsigned int i; - uint32_t update_mask; - uint16_t value; - int rc; - - /* Save the update mask */ - update_mask = x52->update_mask; - /* Reset the device update mask to 0 */ - x52->update_mask = 0; - - for (i = 0; i < 32; i++) { - if (tst_bit(&update_mask, i)) { - switch (i) { - case X52_BIT_SHIFT: - value = tst_bit(&x52->led_mask, X52_BIT_SHIFT) ? X52_SHIFT_ON : X52_SHIFT_OFF; - rc = libx52_control_transfer(x52, X52_SHIFT_INDICATOR, value); - break; - - case X52_BIT_LED_FIRE: - case X52_BIT_LED_A_RED: - case X52_BIT_LED_A_GREEN: - case X52_BIT_LED_B_RED: - case X52_BIT_LED_B_GREEN: - case X52_BIT_LED_D_RED: - case X52_BIT_LED_D_GREEN: - case X52_BIT_LED_E_RED: - case X52_BIT_LED_E_GREEN: - case X52_BIT_LED_T1_RED: - case X52_BIT_LED_T1_GREEN: - case X52_BIT_LED_T2_RED: - case X52_BIT_LED_T2_GREEN: - case X52_BIT_LED_T3_RED: - case X52_BIT_LED_T3_GREEN: - case X52_BIT_LED_POV_RED: - case X52_BIT_LED_POV_GREEN: - case X52_BIT_LED_I_RED: - case X52_BIT_LED_I_GREEN: - case X52_BIT_LED_THROTTLE: - /* The bits correspond exactly to the LED identifiers */ - value = tst_bit(&x52->led_mask, i) ? 1 : 0; - rc = libx52_control_transfer(x52, X52_LED, value | (i << 8)); - break; - - case X52_BIT_MFD_LINE1: - rc = libx52_write_line(x52, 0); - break; - - case X52_BIT_MFD_LINE2: - rc = libx52_write_line(x52, 1); - break; - - case X52_BIT_MFD_LINE3: - rc = libx52_write_line(x52, 2); - break; - - case X52_BIT_POV_BLINK: - value = tst_bit(&x52->led_mask, X52_BIT_POV_BLINK) ? X52_BLINK_ON : X52_BLINK_OFF; - rc = libx52_control_transfer(x52, X52_BLINK_INDICATOR, value); - break; - - case X52_BIT_BRI_MFD: - rc = libx52_control_transfer(x52, X52_MFD_BRIGHTNESS, - x52->mfd_brightness); - break; - - case X52_BIT_BRI_LED: - rc = libx52_control_transfer(x52, X52_LED_BRIGHTNESS, - x52->led_brightness); - break; - - case X52_BIT_MFD_DATE: - rc = libx52_write_date(x52); - break; - - case X52_BIT_MFD_TIME: - case X52_BIT_MFD_OFFS1: - case X52_BIT_MFD_OFFS2: - default: - /* Ignore any spurious bits */ - rc = 0; - break; - } - - if (rc == 0) { - clr_bit(&update_mask, i); - } else { - /* Last transfer failed - reset the update mask */ - x52->update_mask = update_mask; - break; - } - } - } - - return rc; -}