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
Nirenjan Krishnan 2012-10-14 18:02:57 -07:00
parent 76aaf6a6d8
commit 223331342e
5 changed files with 407 additions and 0 deletions

7
libx52/Makefile 100644
View File

@ -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

18
libx52/libx52.h 100644
View File

@ -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 */

107
libx52/x52_common.h 100644
View File

@ -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 */

200
libx52/x52control.c 100644
View File

@ -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;
}

View File

@ -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 */