mirror of https://github.com/nirenjan/libx52.git
Add libx52 API files
Initial frmework of libx52. This library allows the user to write to the X52 joystick MFD and LEDs.pull/3/head
parent
76aaf6a6d8
commit
223331342e
|
@ -0,0 +1,7 @@
|
|||
|
||||
test_x52: x52control.c x52control.h
|
||||
gcc -I /usr/include/libusb-1.0/ x52control.c -lusb-1.0 -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f test_x52 *.o
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBX52_H
|
||||
#define LIBX52_H
|
||||
|
||||
struct libx52_device;
|
||||
typedef struct libx52_device libx52_device;
|
||||
|
||||
#endif /* !defined LIBX52_H */
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef X52JOY_COMMON_H
|
||||
#define X52JOY_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <libusb.h>
|
||||
|
||||
/*
|
||||
* The X52 MFD supports the following:
|
||||
* - 3 lines of 16 characters each
|
||||
* - Clock with HH:MM
|
||||
* - Date with YYMMDD (IIRC)
|
||||
*/
|
||||
#define X52_MFD_LINE_SIZE 16
|
||||
#define X52_MFD_LINES 3
|
||||
|
||||
struct x52_mfd_line {
|
||||
uint8_t text[X52_MFD_LINE_SIZE];
|
||||
uint8_t length;
|
||||
};
|
||||
|
||||
enum x52_mfd_date_format {
|
||||
x52_mfd_format_yymmdd, /* YY-MM-DD */
|
||||
x52_mfd_format_mmddyy, /* MM-DD-YY */
|
||||
x52_mfd_format_ddmmyy, /* DD-MM-YY */
|
||||
x52_mfd_format_max,
|
||||
};
|
||||
|
||||
struct x52_mfd_date {
|
||||
uint8_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t format; /* See format enum */
|
||||
};
|
||||
|
||||
struct x52_mfd_time {
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t h24; /* 24 hour format if 1 */
|
||||
};
|
||||
|
||||
struct x52_mfd_offs {
|
||||
uint16_t min_off; /* Minute offset from clock 0 */
|
||||
uint8_t neg_off; /* Negative offset if 1 */
|
||||
uint8_t h24; /* 24 hour format if 1 */
|
||||
};
|
||||
|
||||
struct libx52_device {
|
||||
libusb_device_handle *hdl;
|
||||
struct libusb_transfer *in_xfer;
|
||||
struct libusb_transfer *ctrl_xfer;
|
||||
|
||||
uint32_t update_mask;
|
||||
uint8_t input_buffer[16];
|
||||
|
||||
uint32_t led_mask;
|
||||
|
||||
struct x52_mfd_line line[X52_MFD_LINES];
|
||||
struct x52_mfd_date date;
|
||||
struct x52_mfd_time time;
|
||||
struct x52_mfd_offs offs[2];
|
||||
};
|
||||
|
||||
#define X52_BIT_SHIFT 0
|
||||
#define X52_BIT_LED_FIRE 1
|
||||
#define X52_BIT_LED_A_RED 2
|
||||
#define X52_BIT_LED_A_GREEN 3
|
||||
#define X52_BIT_LED_B_RED 4
|
||||
#define X52_BIT_LED_B_GREEN 5
|
||||
#define X52_BIT_LED_D_RED 6
|
||||
#define X52_BIT_LED_D_GREEN 7
|
||||
#define X52_BIT_LED_E_RED 8
|
||||
#define X52_BIT_LED_E_GREEN 9
|
||||
#define X52_BIT_LED_T1_RED 10
|
||||
#define X52_BIT_LED_T1_GREEN 11
|
||||
#define X52_BIT_LED_T2_RED 12
|
||||
#define X52_BIT_LED_T2_GREEN 13
|
||||
#define X52_BIT_LED_T3_RED 14
|
||||
#define X52_BIT_LED_T3_GREEN 15
|
||||
#define X52_BIT_LED_POV_RED 16
|
||||
#define X52_BIT_LED_POV_GREEN 17
|
||||
#define X52_BIT_LED_I_RED 18
|
||||
#define X52_BIT_LED_I_GREEN 19
|
||||
#define X52_BIT_LED_THROTTLE 20
|
||||
#define X52_BIT_MFD_LINE1 21
|
||||
#define X52_BIT_MFD_LINE2 22
|
||||
#define X52_BIT_MFD_LINE3 23
|
||||
#define X52_BIT_POV_BLINK 24
|
||||
#define X52_BIT_BRI_MFD 25
|
||||
#define X52_BIT_BRI_LED 26
|
||||
#define X52_BIT_MFD_DATE 27
|
||||
#define X52_BIT_MFD_TIME 28
|
||||
#define X52_BIT_MFD_OFFS1 29
|
||||
#define X52_BIT_MFD_OFFS2 30
|
||||
|
||||
#endif /* !defined X52JOY_COMMON_H */
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver
|
||||
*
|
||||
* Copyright (C) 2012 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 libusb_context *libx52_ctx;
|
||||
|
||||
#define VENDOR_SAITEK 0x06a3
|
||||
#define X52_PROD_X52PRO 0x0762
|
||||
|
||||
static int libx52_check_product(uint16_t idVendor, uint16_t idProduct)
|
||||
{
|
||||
if (idVendor == VENDOR_SAITEK) {
|
||||
switch (idProduct) {
|
||||
case X52_PROD_X52PRO:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void set_bit(uint32_t *value, int bit)
|
||||
{
|
||||
*value |= (1UL << bit);
|
||||
}
|
||||
|
||||
inline void clr_bit(uint32_t *value, uint32_t bit)
|
||||
{
|
||||
*value &= ~(1UL << bit);
|
||||
}
|
||||
|
||||
inline uint32_t tst_bit(uint32_t *value, uint32_t bit)
|
||||
{
|
||||
return (*value & (1UL << bit));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
memcpy(x52->line[line].text, text, 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_date(libx52_device *x52, uint8_t date, uint8_t month, uint8_t year, uint8_t format)
|
||||
{
|
||||
if (!x52 || format >= x52_mfd_format_max) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
x52->date.day = date;
|
||||
x52->date.month = month;
|
||||
x52->date.year = year;
|
||||
x52->date.format = format;
|
||||
|
||||
set_bit(&x52->update_mask, X52_BIT_MFD_DATE);
|
||||
}
|
||||
|
||||
int libx52_set_time(libx52_device *x52, uint8_t hour, uint8_t minute, uint8_t format)
|
||||
{
|
||||
if (!x52 || format >= x52_mfd_format_max) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
x52->time.hour = hour;
|
||||
x52->time.minute = minute;
|
||||
x52->time.h24 = format;
|
||||
|
||||
set_bit(&x52->update_mask, X52_BIT_MFD_TIME);
|
||||
}
|
||||
|
||||
libx52_device* libx52_init(void)
|
||||
{
|
||||
int rc;
|
||||
ssize_t count;
|
||||
int i;
|
||||
libusb_device **list;
|
||||
libusb_device *device;
|
||||
libusb_device_handle *hdl;
|
||||
struct libusb_device_descriptor desc;
|
||||
char pname[64];
|
||||
libx52_device *x52_dev;
|
||||
|
||||
rc = libusb_init(&libx52_ctx);
|
||||
if (rc) {
|
||||
fprintf(stderr, "Unable to initialize libusb; rc=%d\n", rc);
|
||||
return NULL;
|
||||
}
|
||||
libusb_set_debug(libx52_ctx, 3);
|
||||
|
||||
count = libusb_get_device_list(libx52_ctx, &list);
|
||||
for (i = 0; i < count; i++) {
|
||||
device = list[i];
|
||||
printf("Device %d:\n", i);
|
||||
printf("\tBus: %d\n", libusb_get_bus_number(device));
|
||||
printf("\tAddress: %d\n", libusb_get_device_address(device));
|
||||
printf("\tSpeed: %d\n", libusb_get_device_speed(device));
|
||||
|
||||
if (!libusb_get_device_descriptor(device, &desc)) {
|
||||
printf("\tVID/PID: %04x %04x\n", desc.idVendor, desc.idProduct);
|
||||
|
||||
if (libx52_check_product(desc.idVendor, desc.idProduct)) {
|
||||
x52_dev = malloc(sizeof(libx52_device));
|
||||
if (!x52_dev) {
|
||||
fprintf(stderr, "Cannot allocate libx52_device\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = libusb_open(device, &hdl);
|
||||
if (rc) {
|
||||
free(x52_dev);
|
||||
}
|
||||
|
||||
x52_dev->hdl = hdl;
|
||||
|
||||
if(libusb_get_string_descriptor_ascii(hdl, desc.iManufacturer, pname, 64) > 0 || 1) {
|
||||
printf("\tManufacturer: %s\n", pname);
|
||||
}
|
||||
|
||||
if(libusb_get_string_descriptor_ascii(hdl, desc.iProduct, pname, 64) > 0 || 1) {
|
||||
printf("\tProduct: %s\n", pname);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
libusb_free_device_list(list, 1);
|
||||
|
||||
return x52_dev;
|
||||
}
|
||||
|
||||
void libx52_exit(libx52_device *dev)
|
||||
{
|
||||
libusb_close(dev->hdl);
|
||||
free(dev);
|
||||
libusb_exit(libx52_ctx);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int rc;
|
||||
ssize_t count;
|
||||
int i;
|
||||
libx52_device *dev;
|
||||
|
||||
dev = libx52_init();
|
||||
libx52_exit(dev);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Saitek X52 Pro MFD & LED driver
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef X52JOY_COMMANDS_H
|
||||
#define X52JOY_COMMANDS_H
|
||||
|
||||
/* X52 vendor API commands */
|
||||
/* Vendor request - all commands must have this request ID */
|
||||
#define X52_VENDOR_REQUEST 0x91
|
||||
|
||||
/* MFD Text commands */
|
||||
#define X52_MFD_CLEAR_LINE 0x08
|
||||
#define X52_MFD_WRITE_LINE 0x00
|
||||
|
||||
#define X52_MFD_LINE1 0xd1
|
||||
#define X52_MFD_LINE2 0xd2
|
||||
#define X52_MFD_LINE3 0xd4
|
||||
|
||||
/* Brightness commands */
|
||||
#define X52_MFD_BRIGHTNESS 0xb1
|
||||
#define X52_LED_BRIGHTNESS 0xb2
|
||||
|
||||
/* LED set commands */
|
||||
#define X52_LED 0xb8
|
||||
|
||||
/* Time commands */
|
||||
#define X52_TIME_CLOCK1 0xc0
|
||||
#define X52_OFFS_CLOCK2 0xc1
|
||||
#define X52_OFFS_CLOCK3 0xc2
|
||||
|
||||
/* Date commands */
|
||||
#define X52_DATE_DDMM 0xc4
|
||||
#define X52_DATE_YEAR 0xc8
|
||||
|
||||
/* Shift indicator on MFD */
|
||||
#define X52_SHIFT_INDICATOR 0xfd
|
||||
#define X52_SHIFT_ON 0x51
|
||||
#define X52_SHIFT_OFF 0x50
|
||||
|
||||
/* Blink throttle & POV LED */
|
||||
#define X52_BLINK_INDICATOR 0xb4
|
||||
#define X52_BLINK_ON 0x51
|
||||
#define X52_BLINK_OFF 0x50
|
||||
|
||||
/* LED indices */
|
||||
#define X52_LED_FIRE 0x01
|
||||
#define X52_LED_A_RED 0x02
|
||||
#define X52_LED_A_GREEN 0x03
|
||||
#define X52_LED_B_RED 0x04
|
||||
#define X52_LED_B_GREEN 0x05
|
||||
#define X52_LED_D_RED 0x06
|
||||
#define X52_LED_D_GREEN 0x07
|
||||
#define X52_LED_E_RED 0x08
|
||||
#define X52_LED_E_GREEN 0x09
|
||||
#define X52_LED_T1_RED 0x0a
|
||||
#define X52_LED_T1_GREEN 0x0b
|
||||
#define X52_LED_T2_RED 0x0c
|
||||
#define X52_LED_T2_GREEN 0x0d
|
||||
#define X52_LED_T3_RED 0x0e
|
||||
#define X52_LED_T3_GREEN 0x0f
|
||||
#define X52_LED_POV_RED 0x10
|
||||
#define X52_LED_POV_GREEN 0x11
|
||||
#define X52_LED_I_RED 0x12
|
||||
#define X52_LED_I_GREEN 0x13
|
||||
#define X52_LED_THROTTLE 0x14
|
||||
|
||||
#endif /* !defined X52JOY_COMMANDS_H */
|
Loading…
Reference in New Issue