mirror of https://github.com/nirenjan/libx52.git
Breakout functionality into individual files
parent
2ccfd79bd6
commit
995c5b3c63
|
@ -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 */
|
|
@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
#include <libusb.h>
|
||||
|
||||
#include "libx52.h"
|
||||
#include "x52control.h"
|
||||
#include "x52_commands.h"
|
||||
#include "x52_common.h"
|
||||
|
||||
#define VENDOR_SAITEK 0x06a3
|
|
@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue