123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /*
- * Saitek X52 Arduino USB Host Shield Library.
- * Copyright 2016 by Thomas Buck <xythobuz@xythobuz.de>
- *
- * Based on "x52pro-linux" by Nirenjan Krishnan
- * https://github.com/nirenjan/x52pro-linux
- *
- * 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 "x52.h"
-
- //#define DEBUG_OUTPUT Serial
-
- #define TIME_24H_FORMAT
-
- X52::X52(USB* u, HID* h) : usb(u), hid(h), ready(0) { }
-
- void X52::initialize() {
- ready = 0;
-
- if ((!usb) || (!hid)) {
- return;
- }
-
- // Get the USB device descriptor so we can check for a valid PID/VID
- uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
- USB_DEVICE_DESCRIPTOR* udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
- uint8_t ret = usb->getDevDescr(hid->GetAddress(), 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error getting descriptor: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
-
- uint16_t vid = udd->idVendor;
- uint16_t pid = udd->idProduct;
-
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("VID: ");
- DEBUG_OUTPUT.print(vid, DEC);
- DEBUG_OUTPUT.print(" PID: ");
- DEBUG_OUTPUT.println(pid, DEC);
- #endif
-
- if ((vid == 0x06A3) && (pid == 0x0255)) {
- // Saitek X52
- ready = 1;
- } else if ((vid == 0x06A3) && (pid == 0x0762)) {
- // Saitek X52 Pro
- ready = 1;
- } else {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.println("No valid VID/PID found!");
- #endif
- }
- }
-
- void X52::setTime(uint8_t h, uint8_t m) {
- uint8_t ret = sendCommand(X52_TIME_CLOCK1, m | ((h & 0x7F) << 8)
- #ifdef TIME_24H_FORMAT
- | (1 << 15)
- #endif
- );
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error setting time: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
- }
-
- void X52::setTimeOffset(uint8_t cl, int16_t offset) {
- if (offset < -1023) {
- offset = -1023;
- }
-
- if (offset > 1023) {
- offset = 1023;
- }
-
- uint8_t negative = 0;
- if (offset < 0) {
- negative = 1;
- offset = -offset;
- }
-
- uint8_t ret = sendCommand(cl ? X52_OFFS_CLOCK3 : X52_OFFS_CLOCK2,
- (negative << 10) | (offset & 0x03FF)
- #ifdef TIME_24H_FORMAT
- | (1 << 15)
- #endif
- );
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error setting offset: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
- }
-
- void X52::setDate(uint8_t dd, uint8_t mm, uint8_t yy) {
- uint8_t ret = sendCommand(X52_DATE_DDMM, dd | (mm << 8));
- if (!ret) {
- ret = sendCommand(X52_DATE_YEAR, yy);
- }
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error setting date: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
- }
-
- void X52::setBlink(uint8_t state) {
- uint8_t ret = sendCommand(X52_BLINK_INDICATOR, state ? X52_BLINK_ON : X52_BLINK_OFF);
- if (ret != 0) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error setting blink: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
- }
-
- void X52::setShift(uint8_t state) {
- uint8_t ret = sendCommand(X52_SHIFT_INDICATOR, state ? X52_SHIFT_ON : X52_SHIFT_OFF);
- if (ret != 0) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error setting shift: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- }
- }
-
- void X52::setMFDText(uint8_t line, const char* text) {
- const static uint16_t lines[3] = {
- X52_MFD_LINE1,
- X52_MFD_LINE2,
- X52_MFD_LINE3
- };
-
- if (line >= 3) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Invalid line: ");
- DEBUG_OUTPUT.println(line, DEC);
- #endif
- return;
- }
-
- uint8_t ret = sendCommand(X52_MFD_CLEAR_LINE | lines[line], 0);
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error clearing line: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- return;
- }
-
- for (uint8_t i = 0; i < 16; i += 2) {
- if (text[i] == '\0') {
- break;
- }
-
- uint16_t value = text[i];
-
- if (text[i + 1] != '\0') {
- value |= text[i + 1] << 8;
- }
-
- ret = sendCommand(X52_MFD_WRITE_LINE | lines[line], value);
- if (ret) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Error writing to line: ");
- DEBUG_OUTPUT.println(ret, DEC);
- #endif
- return;
- }
-
- if (text[i + 1] == '\0') {
- break;
- }
- }
- }
-
- uint8_t X52::sendCommand(uint16_t command, uint16_t val) {
- if (!ready) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.println("Invalid state!");
- #endif
- return 23;
- }
-
- if ((!usb) || (!hid)) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.println("Invalid objects!");
- #endif
- return 42;
- }
-
- const uint8_t valLo = (val & 0x00FF);
- const uint8_t valHi = (val & 0xFF00) >> 8;
-
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.println("Sending X52 Ctrl-Req...");
- #endif
-
- uint8_t ret = usb->ctrlReq(hid->GetAddress(), 0,
- USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE,
- X52_VENDOR_REQUEST, valLo, valHi, command,
- 0, 0, NULL, NULL);
- if (ret != 0) {
- #ifdef DEBUG_OUTPUT
- DEBUG_OUTPUT.print("Ctrl-Req Error Code: ");
- DEBUG_OUTPUT.println(val, DEC);
- #endif
- }
-
- return ret;
- }
|