mbuesch / razer

Razer device library and tools
http://bues.ch/h/razercfg
GNU General Public License v2.0
253 stars 50 forks source link

Ouroboros support #45

Open Kernald opened 9 years ago

Kernald commented 9 years ago

Owning an Ouroboros mouse, I tried to hack support for it. It's a Synapse one. I mainly copied code from the Imperator one. Here's what I have:

diff --git a/librazer/CMakeLists.txt b/librazer/CMakeLists.txt
index 19f402c..b537815 100644
--- a/librazer/CMakeLists.txt
+++ b/librazer/CMakeLists.txt
@@ -18,7 +18,8 @@ add_library(razer SHARED
        hw_lachesis5k6.c
        hw_naga.c
        hw_imperator.c
-       hw_taipan.c)
+       hw_taipan.c
+       hw_ouroboros.c)

 set_target_properties(razer PROPERTIES COMPILE_FLAGS ${GENERIC_COMPILE_FLAGS})

diff --git a/librazer/hw_ouroboros.c b/librazer/hw_ouroboros.c
new file mode 100644
index 0000000..cf7432f
--- /dev/null
+++ b/librazer/hw_ouroboros.c
@@ -0,0 +1,44 @@
+/*
+ *   Lowlevel hardware access for the
+ *   Razer Ouroboros mouse
+ *
+ *   Important notice:
+ *   This hardware driver is based on reverse engineering, only.
+ *
+ *   Copyright (C) 2012 Michael Buesch <m@bues.ch>
+ *
+ *   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; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include "hw_ouroboros.h"
+#include "synapse.h"
+#include "razer_private.h"
+
+
+int razer_ouroboros_init(struct razer_mouse *m,
+            struct libusb_device *usbdev)
+{
+   int err;
+
+   err = razer_synapse_init(m, NULL, 0);
+   if (err)
+       return err;
+
+   razer_generic_usb_gen_idstr(usbdev, m->usb_ctx->h, "Ouroboros", 1,
+                   razer_synapse_get_serial(m), m->idstr);
+
+   return 0;
+}
+
+void razer_ouroboros_release(struct razer_mouse *m)
+{
+   razer_synapse_exit(m);
+}
diff --git a/librazer/hw_ouroboros.h b/librazer/hw_ouroboros.h
new file mode 100644
index 0000000..0e723b5
--- /dev/null
+++ b/librazer/hw_ouroboros.h
@@ -0,0 +1,11 @@
+#ifndef RAZER_HW_OUROBOROS_H_
+#define RAZER_HW_OUROBOROS_H_
+
+#include "razer_private.h"
+
+
+int razer_ouroboros_init(struct razer_mouse *m,
+            struct libusb_device *udev);
+void razer_ouroboros_release(struct razer_mouse *m);
+
+#endif /* RAZER_HW_OUROBOROS_H_ */
diff --git a/librazer/librazer.c b/librazer/librazer.c
index 80979e8..603c9e6 100644
--- a/librazer/librazer.c
+++ b/librazer/librazer.c
@@ -30,6 +30,7 @@
 #include "hw_boomslangce.h"
 #include "hw_imperator.h"
 #include "hw_taipan.h"
+#include "hw_ouroboros.h"

 #include <stdint.h>
 #include <stdlib.h>
@@ -133,6 +134,12 @@ static const struct razer_mouse_base_ops razer_taipan_base_ops = {
    .release        = razer_taipan_release,
 };

+static const struct razer_mouse_base_ops razer_ouroboros_base_ops = {
+   .type           = RAZER_MOUSETYPE_OUROBOROS,
+   .init           = razer_ouroboros_init,
+   .release        = razer_ouroboros_release,
+};
+
 #define USBVENDOR_ANY  0xFFFF
 #define USBPRODUCT_ANY 0xFFFF

@@ -161,6 +168,7 @@ static const struct razer_usb_device razer_usbdev_table[] = {
    USB_MOUSE(0x1532, 0x0005, &razer_boomslangce_base_ops),
    USB_MOUSE(0x1532, 0x0017, &razer_imperator_base_ops),
    USB_MOUSE(0x1532, 0x0034, &razer_taipan_base_ops),
+   USB_MOUSE(0x1532, 0x0032, &razer_ouroboros_base_ops),
    { 0, }, /* List end */
 };
 #undef USB_MOUSE
diff --git a/librazer/librazer.h b/librazer/librazer.h
index fa42a40..83ada3c 100644
--- a/librazer/librazer.h
+++ b/librazer/librazer.h
@@ -197,6 +197,7 @@ enum razer_mouse_res {
   * @RAZER_MOUSETYPE_BOOMSLANGCE: A "Boomslang Collector's Edition" mouse
   * @RAZER_MOUSETYPE_IMPERATOR: An "Imperator" mouse
   * @RAZER_MOUSETYPE_TAIPAN: A "Taipan" mouse
+  * @RAZER_MOUSETYPE_OUROBOROS: A "Ouroboros" mouse
   */

 enum razer_mouse_type {
@@ -208,6 +209,7 @@ enum razer_mouse_type {
    RAZER_MOUSETYPE_BOOMSLANGCE,
    RAZER_MOUSETYPE_IMPERATOR,
    RAZER_MOUSETYPE_TAIPAN,
+   RAZER_MOUSETYPE_OUROBOROS,
 };

 /** struct razer_button_function - A logical button function

Looks pretty simple. However, I heard there is no such thing as a simple Razer mouse... And in fact, it doesn't work:

librazer: synapse: Invalid magic on received request
librazer: synapse: Failed to get firmware version

I have access to Windows so I can make a dump. Do you have any hint on what to look for, and where?

Thanks.

deandersson commented 9 years ago

Hi, I actually tried this for about a year ago and got the same error as you, I decided to try and base the ouroboros on the taipan instead. Never actually pushed it to github because it never got more than a ugly hack and I soon had to go back to windows.

Im back on linux and this got me motivated again, I will try and see if I can clean up the code, but in the meantime you can do what you did but use the taipan code instead and you will have basic support. :smile:

zliebersbach commented 9 years ago

Hello, anyone had any luck on this? I'm willing to lend a hand with testing if needed, because I have an Ouroboros.

haoanw commented 8 years ago

@Kernald @wincinderith @deandersson I've tried to use this same "ugly hack" method on my new Mamba Tournament Edition, but i choose the Deathadder Chroma as a template, remain all the part inside 'hw_deathadder_chroma.c / hw_deathadder_chroma.h' except the names. Now the razercfg can detect the mouse (appeared after razercfg -s) and DPI adjusting is also working (but the buttons for it didn't work anymore, it use to work without the driver, of course the DA Chroma doesnt have these buttons so they are not mapped). Only the lights didn't cos it has much more lights than DA Chroma. That's what ive got so far, now i try to analyze the pcap files i recorded in oder to find some informtion about commands for lights. It is quite difficult for me cos i know nothing about USB HID agreement.

mbuesch commented 8 years ago

It is quite difficult for me cos i know nothing about USB HID agreement.

You do not need to know anything about HID, because the configuration takes place in non-HID packets.

haoanw commented 8 years ago

@mbuesch thanks for your reply. Here are some more information. The pcap files i have recorded were quite different from each other.

DA_Chroma.pcap : only has 'URB_INTERRUPT in' type, and the data only has one direction, which is from Source [2.1 (i believe it's usb id)] to Destination [host].

MAMBA_TE.pcap: has 5 types of date, those are 'URB_CONTROL out', 'URB_CONTROL in', 'URB_INTERRUPT in', 'CLEAR FEATURE Status', and 'SET CONFIGURATION Status'. and the datas has both flowing directions. why it is like that?

accordingly, the SET CONFIGURATION Status data (MAMBA_TE) has 28 bytes, and only variable bits are from bit 2nd to bit 5th (4 bits), is this indicating anything?

haoanw commented 8 years ago

@mbuesch one more question: in hw_deathadder_chroma.c, (ln 64). In the second enum, the last three data show up in the deathadder_chroma_send_setled * ( * ) function, i assume it is related to the operation of the led lights, how are those obtained from the pcap file?

`enum deathadder_chroma_request_size { DEATHADDER_CHROMA_REQUEST_SIZE_INIT = 0x02, DEATHADDER_CHROMA_REQUEST_SIZE_SET_RESOLUTION = 0x07, DEATHADDER_CHROMA_REQUEST_SIZE_GET_FIRMWARE = 0x04, DEATHADDER_CHROMA_REQUEST_SIZE_GET_SERIAL_NO = 0x16, DEATHADDER_CHROMA_REQUEST_SIZE_SET_FREQUENCY = 0x01, DEATHADDER_CHROMA_REQUEST_SIZE_SET_LED_STATE = 0x03, DEATHADDER_CHROMA_REQUEST_SIZE_SET_LED_MODE = 0x03, DEATHADDER_CHROMA_REQUEST_SIZE_SET_LED_COLOR = 0x05 };

enum deathadder_chroma_request { DEATHADDER_CHROMA_REQUEST_INIT = 0x0004, DEATHADDER_CHROMA_REQUEST_SET_RESOLUTION = 0x0405, DEATHADDER_CHROMA_REQUEST_GET_FIRMWARE = 0x0087, DEATHADDER_CHROMA_REQUEST_GET_SERIAL_NO = 0x0082, DEATHADDER_CHROMA_REQUEST_SET_FREQUENCY = 0x0005, DEATHADDER_CHROMA_REQUEST_SET_LED_STATE = 0x0300, DEATHADDER_CHROMA_REQUEST_SET_LED_MODE = 0x0302, DEATHADDER_CHROMA_REQUEST_SET_LED_COLOR = 0x0301 };` (i tried several times, it won't show up in form of code...)

mbuesch commented 8 years ago

@haoanw

DA_Chroma.pcap : only has 'URB_INTERRUPT in' type, and the data only has one direction, which is from Source [2.1 (i believe it's usb id)] to Destination [host]. MAMBA_TE.pcap: has 5 types of date, those are 'URB_CONTROL out', 'URB_CONTROL in', 'URB_INTERRUPT in', 'CLEAR FEATURE Status', and 'SET CONFIGURATION Status'. and the datas has both flowing directions. why it is like that?

Because you did something wrong? :) I can't tell how you capture that stuff. But one thing to do is: Do not move the mouse and do not press any key while capturing. That eliminates 99% of all unrelated packets. (Use a second mouse to operate wireshark).

i assume it is related to the operation of the led lights, how are those obtained from the pcap file?

Well, it will show up in the data somewhere according to the configuration packet(s) format(s). See the driver for details. I did not write that driver, so I would have to read the driver on my own to tell you more about the data format. But you can just read the driver code yourself then. Just see the data structures that define the packet formats and see the code that prepares these packets and sends them.