From 7c07ba0f7bd9ddcc5a47b818d3bbc0bfece3c292 Mon Sep 17 00:00:00 2001
From: nightsky30 <6024315+nightsky30@users.noreply.github.com>
Date: Sun, 29 Nov 2020 20:42:17 -0600
Subject: [PATCH] Add support for Razer Mouse Bungee V3 Chroma

---
 README.md                                     |  1 +
 daemon/openrazer_daemon/hardware/accessory.py | 17 ++++++++
 driver/razeraccessory_driver.c                | 41 +++++++++++++++++--
 driver/razeraccessory_driver.h                |  1 +
 driver/razerchromacommon.c                    |  2 +-
 ...io.github.openrazer.openrazer.metainfo.xml |  1 +
 install_files/udev/99-razer.rules             |  2 +-
 .../_fake_driver/razermousebungeev3chroma.cfg | 15 +++++++
 8 files changed, 74 insertions(+), 6 deletions(-)
 create mode 100644 pylib/openrazer/_fake_driver/razermousebungeev3chroma.cfg

diff --git a/README.md b/README.md
index 7051140f..86111dc9 100644
--- a/README.md
+++ b/README.md
@@ -158,6 +158,7 @@ The devices below are fully feature supported by OpenRazer, which means all avai
 | Razer Chroma Mug Holder                       |  1532:0F07  |
 | Razer Base Station Chroma                     |  1532:0F08  |
 | Razer Chroma Hardware Development Kit (HDK)   |  1532:0F09  |
+| Razer Mouse Bungee V3 Chroma                  |  1532:0F1D  |
 
 #### Determining the Device ID
 Razer devices use a USB VID (Vendor ID) of `1532`. You can identify the USB PID (Product ID) by typing:
diff --git a/daemon/openrazer_daemon/hardware/accessory.py b/daemon/openrazer_daemon/hardware/accessory.py
index 6279c7b6..43d3b9f3 100644
--- a/daemon/openrazer_daemon/hardware/accessory.py
+++ b/daemon/openrazer_daemon/hardware/accessory.py
@@ -82,3 +82,20 @@ class RazerNommoPro(_RazerDeviceBrightnessSuspend):
                'set_custom_effect', 'set_key_row']
 
     DEVICE_IMAGE = "https://d4kkpd69xt9l7.cloudfront.net/sys-master/root/h89/hc4/9003754717214/razer-nommo-pro-audio-04.jpg"
+
+
+class RazerMouseBungeeV3Chroma(_RazerDeviceBrightnessSuspend):
+    """
+    Class for the Razer Mouse Bungee V3 Chroma
+    """
+    EVENT_FILE_REGEX = re.compile(r'.*Razer_Mouse_Bungee_V3_Chroma-if01-event-kbd')
+
+    USB_VID = 0x1532
+    USB_PID = 0x0F1D
+    HAS_MATRIX = True
+    MATRIX_DIMS = [1, 8]
+    METHODS = ['get_device_type_accessory', 'set_static_effect', 'set_wave_effect', 'set_spectrum_effect',
+               'set_none_effect', 'set_breath_random_effect', 'set_breath_single_effect', 'set_breath_dual_effect',
+               'set_custom_effect', 'set_key_row']
+
+    DEVICE_IMAGE = "https://assets2.razerzone.com/images/pnx.assets/03970e1bd220f3d2985c5e0060fb3bbf/razer-mouse-bungee-v3-chroma.png"
diff --git a/driver/razeraccessory_driver.c b/driver/razeraccessory_driver.c
index 04732b5a..833ca112 100644
--- a/driver/razeraccessory_driver.c
+++ b/driver/razeraccessory_driver.c
@@ -160,6 +160,10 @@ static ssize_t razer_attr_read_device_type(struct device *dev, struct device_att
         device_type = "Razer Kraken Kitty Edition\n";
         break;
 
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+        device_type = "Razer Mouse Bungee V3 Chroma\n";
+        break;
+
     default:
         device_type = "Unknown Device\n";
         break;
@@ -203,6 +207,7 @@ static ssize_t razer_attr_write_mode_spectrum(struct device *dev, struct device_
     case USB_DEVICE_ID_RAZER_CORE:
     case USB_DEVICE_ID_RAZER_CHROMA_MUG:
         report = razer_chroma_standard_matrix_effect_spectrum(VARSTORE, BACKLIGHT_LED);
+        report.transaction_id.id = 0x3F;
         break;
 
     case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
@@ -213,6 +218,12 @@ static ssize_t razer_attr_write_mode_spectrum(struct device *dev, struct device_
     case USB_DEVICE_ID_RAZER_NOMMO_PRO:
     case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
         report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+        report.transaction_id.id = 0x3F;
+        break;
+
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+        report = razer_chroma_extended_matrix_effect_spectrum(VARSTORE, ZERO_LED);
+        report.transaction_id.id = 0x1F;
         break;
 
     default:
@@ -220,8 +231,6 @@ static ssize_t razer_attr_write_mode_spectrum(struct device *dev, struct device_
         break;
     }
 
-    report.transaction_id.id = 0x3F;
-
     mutex_lock(&device->lock);
     razer_send_payload(device->usb_dev, &report);
     mutex_unlock(&device->lock);
@@ -327,6 +336,7 @@ static ssize_t razer_attr_write_mode_none(struct device *dev, struct device_attr
         break;
 
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report = razer_chroma_extended_matrix_effect_none(VARSTORE, ZERO_LED);
         report.transaction_id.id = 0x1F;
         break;
@@ -400,6 +410,7 @@ static ssize_t razer_attr_write_mode_custom(struct device *dev, struct device_at
         break;
 
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report = razer_chroma_extended_matrix_effect_custom_frame();
         report.transaction_id.id = 0x1F;
         break;
@@ -447,6 +458,7 @@ static ssize_t razer_attr_write_mode_static(struct device *dev, struct device_at
             break;
 
         case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             report = razer_chroma_extended_matrix_effect_static(VARSTORE, ZERO_LED, (struct razer_rgb*) & buf[0]);
             report.transaction_id.id = 0x1F;
             break;
@@ -484,6 +496,7 @@ static ssize_t razer_attr_write_mode_wave(struct device *dev, struct device_attr
     case USB_DEVICE_ID_RAZER_CORE:
     case USB_DEVICE_ID_RAZER_CHROMA_MUG:
         report = razer_chroma_standard_matrix_effect_wave(VARSTORE, BACKLIGHT_LED, direction);
+        report.transaction_id.id = 0x3F;
         break;
 
     case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX:
@@ -492,6 +505,12 @@ static ssize_t razer_attr_write_mode_wave(struct device *dev, struct device_attr
     case USB_DEVICE_ID_RAZER_NOMMO_PRO:
     case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
         report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction);
+        report.transaction_id.id = 0x3F;
+        break;
+
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
+        report = razer_chroma_extended_matrix_effect_wave(VARSTORE, ZERO_LED, direction);
+        report.transaction_id.id = 0x1F;
         break;
 
     default:
@@ -499,8 +518,6 @@ static ssize_t razer_attr_write_mode_wave(struct device *dev, struct device_attr
         break;
     }
 
-    report.transaction_id.id = 0x3F;
-
     mutex_lock(&device->lock);
     razer_send_payload(device->usb_dev, &report);
     mutex_unlock(&device->lock);
@@ -545,6 +562,7 @@ static ssize_t razer_attr_write_mode_breath(struct device *dev, struct device_at
         break;
 
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         switch(count) {
         case 3: // Single colour mode
             report = razer_chroma_extended_matrix_effect_breathing_single(VARSTORE, ZERO_LED, (struct razer_rgb *)&buf[0]);
@@ -664,6 +682,7 @@ static ssize_t razer_attr_write_set_key_row(struct device *dev, struct device_at
             break;
 
         case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             report = razer_chroma_extended_matrix_set_custom_frame2(row_id, start_col, stop_col, (unsigned char*)&buf[offset], 0);
             report.transaction_id.id = 0x1F;
             break;
@@ -717,6 +736,7 @@ static ssize_t razer_attr_read_get_serial(struct device *dev, struct device_attr
         break;
 
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report.transaction_id.id = 0x1F;
         response_report = razer_send_payload(device->usb_dev, &report);
         strncpy(&serial_string[0], &response_report.arguments[0], 22);
@@ -744,6 +764,7 @@ static ssize_t razer_attr_read_get_firmware_version(struct device *dev, struct d
 
     switch(device->usb_pid) {
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report.transaction_id.id = 0x1F;
         break;
 
@@ -785,6 +806,7 @@ static ssize_t razer_attr_write_device_mode(struct device *dev, struct device_at
 
         switch(device->usb_pid) {
         case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             report.transaction_id.id = 0x1F;
             break;
         }
@@ -823,6 +845,7 @@ static ssize_t razer_attr_read_device_mode(struct device *dev, struct device_att
 
     switch(device->usb_pid) {
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report.transaction_id.id = 0x1F;
         break;
     }
@@ -860,6 +883,7 @@ static ssize_t razer_attr_write_set_brightness(struct device *dev, struct device
         break;
 
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         report = razer_chroma_extended_matrix_brightness(VARSTORE, ZERO_LED, brightness);
         report.transaction_id.id = 0x1F;
         device->saved_brightness = brightness;
@@ -907,6 +931,7 @@ static ssize_t razer_attr_read_set_brightness(struct device *dev, struct device_
     case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA:
     case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED:
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         brightness = device->saved_brightness;
         break;
 
@@ -1042,6 +1067,7 @@ static int razer_accessory_probe(struct hid_device *hdev, const struct hid_devic
     switch(usb_dev->descriptor.idProduct) {
     case USB_DEVICE_ID_RAZER_CORE:
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         expected_protocol = 0;
         break;
 
@@ -1096,6 +1122,7 @@ static int razer_accessory_probe(struct hid_device *hdev, const struct hid_devic
         case USB_DEVICE_ID_RAZER_CHROMA_MUG:
         case USB_DEVICE_ID_RAZER_CHROMA_BASE:
         case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_spectrum);            // Spectrum effect
         }
 
@@ -1107,6 +1134,7 @@ static int razer_accessory_probe(struct hid_device *hdev, const struct hid_devic
         case USB_DEVICE_ID_RAZER_CHROMA_BASE:
         case USB_DEVICE_ID_RAZER_NOMMO_PRO:
         case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             CREATE_DEVICE_FILE(&hdev->dev, &dev_attr_matrix_effect_wave);                // Wave effect
             break;
         }
@@ -1180,6 +1208,7 @@ static void razer_accessory_disconnect(struct hid_device *hdev)
     switch(usb_dev->descriptor.idProduct) {
     case USB_DEVICE_ID_RAZER_CORE:
     case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION:
+    case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
         expected_protocol = 0;
         break;
 
@@ -1225,6 +1254,7 @@ static void razer_accessory_disconnect(struct hid_device *hdev)
         case USB_DEVICE_ID_RAZER_CHROMA_MUG:
         case USB_DEVICE_ID_RAZER_CHROMA_BASE:
         case USB_DEVICE_ID_RAZER_CHROMA_HDK:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             device_remove_file(&hdev->dev, &dev_attr_matrix_effect_spectrum);            // Spectrum effect
         }
 
@@ -1236,6 +1266,7 @@ static void razer_accessory_disconnect(struct hid_device *hdev)
         case USB_DEVICE_ID_RAZER_CHROMA_BASE:
         case USB_DEVICE_ID_RAZER_NOMMO_PRO:
         case USB_DEVICE_ID_RAZER_NOMMO_CHROMA:
+        case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA:
             device_remove_file(&hdev->dev, &dev_attr_matrix_effect_wave);                // Wave effect
             break;
         }
@@ -1250,6 +1281,7 @@ static void razer_accessory_disconnect(struct hid_device *hdev)
             device_remove_file(&hdev->dev, &dev_attr_matrix_reactive_trigger);           // Reactive trigger
             break;
         }
+
         switch(usb_dev->descriptor.idProduct) {
         case USB_DEVICE_ID_RAZER_CHROMA_MUG:
             device_remove_file(&hdev->dev, &dev_attr_is_mug_present);                    // Is cup present
@@ -1304,6 +1336,7 @@ static const struct hid_device_id razer_devices[] = {
     { HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_NOMMO_PRO) },
     { HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_NOMMO_CHROMA) },
     { HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION) },
+    { HID_USB_DEVICE(USB_VENDOR_ID_RAZER,USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA) },
     { 0 }
 };
 
diff --git a/driver/razeraccessory_driver.h b/driver/razeraccessory_driver.h
index 4372587a..cdbfb54b 100644
--- a/driver/razeraccessory_driver.h
+++ b/driver/razeraccessory_driver.h
@@ -23,6 +23,7 @@
 #define USB_DEVICE_ID_RAZER_CHROMA_BASE 0x0F08
 #define USB_DEVICE_ID_RAZER_CHROMA_HDK 0x0F09
 #define USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION 0x0F19
+#define USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA 0x0F1D
 
 #define RAZER_ACCESSORY_WAIT_MIN_US 600
 #define RAZER_ACCESSORY_WAIT_MAX_US 1000
diff --git a/driver/razerchromacommon.c b/driver/razerchromacommon.c
index b66767cd..3f704fc6 100644
--- a/driver/razerchromacommon.c
+++ b/driver/razerchromacommon.c
@@ -551,7 +551,7 @@ struct razer_report razer_chroma_extended_matrix_effect_wave(unsigned char varia
     direction = clamp_u8(direction, 0x00, 0x02);
 
     report.arguments[3] = direction;
-    report.arguments[4] = 0x28; // Unknown
+    report.arguments[4] = 0x28; // Speed, lower values are faster
     return report;
 }
 
diff --git a/install_files/appstream/io.github.openrazer.openrazer.metainfo.xml b/install_files/appstream/io.github.openrazer.openrazer.metainfo.xml
index 2c54b3d4..c1468889 100644
--- a/install_files/appstream/io.github.openrazer.openrazer.metainfo.xml
+++ b/install_files/appstream/io.github.openrazer.openrazer.metainfo.xml
@@ -140,5 +140,6 @@
     <modalias>usb:v1532p0F08d*</modalias>
     <modalias>usb:v1532p0F09d*</modalias>
     <modalias>usb:v1532p0F19d*</modalias>
+    <modalias>usb:v1532p0F1Dd*</modalias>
   </provides>
 </component>
diff --git a/install_files/udev/99-razer.rules b/install_files/udev/99-razer.rules
index 9a13932b..8d03a06e 100644
--- a/install_files/udev/99-razer.rules
+++ b/install_files/udev/99-razer.rules
@@ -20,7 +20,7 @@ ATTRS{idProduct}=="0501|0504|0506|0510|0527", \
     ENV{ID_RAZER_CHROMA}="1", ENV{RAZER_DRIVER}="razerkraken"
 
 # Accessories (Speakers, Mousemats, Razer Core, etc)
-ATTRS{idProduct}=="0068|0215|0517|0518|0c00|0c01|0c02|0f07|0f08|0f09|0f19", \
+ATTRS{idProduct}=="0068|0215|0517|0518|0c00|0c01|0c02|0f07|0f08|0f09|0f19|0f1d", \
     ATTRS{idVendor}=="1532", \
     ENV{ID_RAZER_CHROMA}="1", ENV{RAZER_DRIVER}="razeraccessory"
 
diff --git a/pylib/openrazer/_fake_driver/razermousebungeev3chroma.cfg b/pylib/openrazer/_fake_driver/razermousebungeev3chroma.cfg
new file mode 100644
index 00000000..10980bf9
--- /dev/null
+++ b/pylib/openrazer/_fake_driver/razermousebungeev3chroma.cfg
@@ -0,0 +1,15 @@
+[device]
+dir_name = 0003:1532:0F1D.0001
+name = Razer Mouse Bungee V3 Chroma
+files = r,device_serial,XX0000000F1D
+        r,device_type,%(name)s
+        r,firmware_version,v1.0
+        rw,matrix_brightness,0
+        w,matrix_custom_frame
+        w,matrix_effect_breath
+        w,matrix_effect_custom
+        w,matrix_effect_none
+        w,matrix_effect_spectrum
+        w,matrix_effect_static
+        w,matrix_effect_wave
+        r,version,1.0.0
-- 
GitLab