diff --git a/jsonrpc.go b/jsonrpc.go
index b1b36c5..1f3a2cb 100644
--- a/jsonrpc.go
+++ b/jsonrpc.go
@@ -764,6 +764,17 @@ func rpcSetCloudUrl(apiUrl string, appUrl string) error {
 	return nil
 }
 
+var currentScrollSensitivity string = "default"
+
+func rpcGetScrollSensitivity() (string, error) {
+	return currentScrollSensitivity, nil
+}
+
+func rpcSetScrollSensitivity(sensitivity string) error {
+	currentScrollSensitivity = sensitivity
+	return nil
+}
+
 var rpcHandlers = map[string]RPCHandler{
 	"ping":                   {Func: rpcPing},
 	"getDeviceID":            {Func: rpcGetDeviceID},
@@ -823,4 +834,6 @@ var rpcHandlers = map[string]RPCHandler{
 	"getSerialSettings":      {Func: rpcGetSerialSettings},
 	"setSerialSettings":      {Func: rpcSetSerialSettings, Params: []string{"settings"}},
 	"setCloudUrl":            {Func: rpcSetCloudUrl, Params: []string{"apiUrl", "appUrl"}},
+	"getScrollSensitivity":   {Func: rpcGetScrollSensitivity},
+	"setScrollSensitivity":   {Func: rpcSetScrollSensitivity, Params: []string{"sensitivity"}},
 }
diff --git a/ui/src/components/WebRTCVideo.tsx b/ui/src/components/WebRTCVideo.tsx
index bb17e39..1587d29 100644
--- a/ui/src/components/WebRTCVideo.tsx
+++ b/ui/src/components/WebRTCVideo.tsx
@@ -1,5 +1,6 @@
 import { useCallback, useEffect, useRef, useState } from "react";
 import {
+  useDeviceSettingsStore,
   useHidStore,
   useMouseStore,
   useRTCStore,
@@ -144,19 +145,28 @@ export default function WebRTCVideo() {
     [sendMouseMovement, videoClientHeight, videoClientWidth, videoWidth, videoHeight],
   );
 
+  const trackpadSensitivity = useDeviceSettingsStore(state => state.trackpadSensitivity);
+  const mouseSensitivity = useDeviceSettingsStore(state => state.mouseSensitivity);
+  const clampMin = useDeviceSettingsStore(state => state.clampMin);
+  const clampMax = useDeviceSettingsStore(state => state.clampMax);
+  const blockDelay = useDeviceSettingsStore(state => state.blockDelay);
+  const trackpadThreshold = useDeviceSettingsStore(state => state.trackpadThreshold);
+
   const mouseWheelHandler = useCallback(
     (e: WheelEvent) => {
       if (blockWheelEvent) return;
-      e.preventDefault();
 
-      // Define a scaling factor to adjust scrolling sensitivity
-      const scrollSensitivity = 0.8; // Adjust this value to change scroll speed
+      // Determine if the wheel event is from a trackpad or a mouse wheel
+      const isTrackpad = Math.abs(e.deltaY) < trackpadThreshold;
+
+      // Apply appropriate sensitivity based on input device
+      const scrollSensitivity = isTrackpad ? trackpadSensitivity : mouseSensitivity;
 
       // Calculate the scroll value
       const scroll = e.deltaY * scrollSensitivity;
 
-      // Clamp the scroll value to a reasonable range (e.g., -15 to 15)
-      const clampedScroll = Math.max(-4, Math.min(4, scroll));
+      // Apply clamping
+      const clampedScroll = Math.max(clampMin, Math.min(clampMax, scroll));
 
       // Round to the nearest integer
       const roundedScroll = Math.round(clampedScroll);
@@ -164,13 +174,22 @@ export default function WebRTCVideo() {
       // Invert the scroll value to match expected behavior
       const invertedScroll = -roundedScroll;
 
-      console.log("wheelReport", { wheelY: invertedScroll });
       send("wheelReport", { wheelY: invertedScroll });
 
+      // Apply blocking delay
       setBlockWheelEvent(true);
-      setTimeout(() => setBlockWheelEvent(false), 50);
+      setTimeout(() => setBlockWheelEvent(false), blockDelay);
     },
-    [blockWheelEvent, send],
+    [
+      blockDelay,
+      blockWheelEvent,
+      clampMax,
+      clampMin,
+      mouseSensitivity,
+      send,
+      trackpadSensitivity,
+      trackpadThreshold,
+    ],
   );
 
   const resetMousePosition = useCallback(() => {
@@ -356,7 +375,10 @@ export default function WebRTCVideo() {
       videoElmRefValue.addEventListener("pointerdown", mouseMoveHandler, { signal });
       videoElmRefValue.addEventListener("pointerup", mouseMoveHandler, { signal });
       videoElmRefValue.addEventListener("keyup", videoKeyUpHandler, { signal });
-      videoElmRefValue.addEventListener("wheel", mouseWheelHandler, { signal });
+      videoElmRefValue.addEventListener("wheel", mouseWheelHandler, {
+        signal,
+        passive: true,
+      });
       videoElmRefValue.addEventListener(
         "contextmenu",
         (e: MouseEvent) => e.preventDefault(),
diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts
index 3dfc96c..ac8ad7d 100644
--- a/ui/src/hooks/stores.ts
+++ b/ui/src/hooks/stores.ts
@@ -306,6 +306,78 @@ export const useSettingsStore = create(
   ),
 );
 
+export interface DeviceSettingsState {
+  trackpadSensitivity: number;
+  mouseSensitivity: number;
+  clampMin: number;
+  clampMax: number;
+  blockDelay: number;
+  trackpadThreshold: number;
+  scrollSensitivity: "low" | "default" | "high";
+  setScrollSensitivity: (sensitivity: DeviceSettingsState["scrollSensitivity"]) => void;
+}
+
+export const useDeviceSettingsStore = create<DeviceSettingsState>(set => ({
+  trackpadSensitivity: 3.0,
+  mouseSensitivity: 5.0,
+  clampMin: -8,
+  clampMax: 8,
+  blockDelay: 25,
+  trackpadThreshold: 10,
+
+  scrollSensitivity: "default",
+  setScrollSensitivity: sensitivity => {
+    const wheelSettings: Record<
+      DeviceSettingsState["scrollSensitivity"],
+      {
+        trackpadSensitivity: DeviceSettingsState["trackpadSensitivity"];
+        mouseSensitivity: DeviceSettingsState["mouseSensitivity"];
+        clampMin: DeviceSettingsState["clampMin"];
+        clampMax: DeviceSettingsState["clampMax"];
+        blockDelay: DeviceSettingsState["blockDelay"];
+        trackpadThreshold: DeviceSettingsState["trackpadThreshold"];
+      }
+    > = {
+      low: {
+        trackpadSensitivity: 2.0,
+        mouseSensitivity: 3.0,
+        clampMin: -6,
+        clampMax: 6,
+        blockDelay: 30,
+        trackpadThreshold: 10,
+      },
+      default: {
+        trackpadSensitivity: 3.0,
+        mouseSensitivity: 5.0,
+        clampMin: -8,
+        clampMax: 8,
+        blockDelay: 25,
+        trackpadThreshold: 10,
+      },
+      high: {
+        trackpadSensitivity: 4.0,
+        mouseSensitivity: 6.0,
+        clampMin: -9,
+        clampMax: 9,
+        blockDelay: 20,
+        trackpadThreshold: 10,
+      },
+    };
+
+    const settings = wheelSettings[sensitivity];
+
+    return set({
+      trackpadSensitivity: settings.trackpadSensitivity,
+      trackpadThreshold: settings.trackpadThreshold,
+      mouseSensitivity: settings.mouseSensitivity,
+      clampMin: settings.clampMin,
+      clampMax: settings.clampMax,
+      blockDelay: settings.blockDelay,
+      scrollSensitivity: sensitivity,
+    });
+  },
+}));
+
 export interface RemoteVirtualMediaState {
   source: "WebRTC" | "HTTP" | "Storage" | null;
   mode: "CDROM" | "Disk" | null;
diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx
index e7dc4b8..9956ecb 100644
--- a/ui/src/routes/devices.$id.settings.mouse.tsx
+++ b/ui/src/routes/devices.$id.settings.mouse.tsx
@@ -4,15 +4,22 @@ import { Checkbox } from "@/components/Checkbox";
 import { GridCard } from "@/components/Card";
 import PointingFinger from "@/assets/pointing-finger.svg";
 import { CheckCircleIcon } from "@heroicons/react/16/solid";
-import { useSettingsStore } from "@/hooks/stores";
+import { useDeviceSettingsStore, useSettingsStore } from "@/hooks/stores";
 import notifications from "@/notifications";
-import { useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
 import { useJsonRpc } from "@/hooks/useJsonRpc";
 import { cx } from "../cva.config";
+import { SelectMenuBasic } from "../components/SelectMenuBasic";
+
+type ScrollSensitivity = "low" | "default" | "high";
 
 export default function SettingsKeyboardMouseRoute() {
   const hideCursor = useSettingsStore(state => state.isCursorHidden);
   const setHideCursor = useSettingsStore(state => state.setCursorVisibility);
+  const scrollSensitivity = useDeviceSettingsStore(state => state.scrollSensitivity);
+  const setScrollSensitivity = useDeviceSettingsStore(
+    state => state.setScrollSensitivity,
+  );
 
   const [jiggler, setJiggler] = useState(false);
 
@@ -23,7 +30,12 @@ export default function SettingsKeyboardMouseRoute() {
       if ("error" in resp) return;
       setJiggler(resp.result as boolean);
     });
-  }, [send]);
+
+    send("getScrollSensitivity", {}, resp => {
+      if ("error" in resp) return;
+      setScrollSensitivity(resp.result as ScrollSensitivity);
+    });
+  }, [send, setScrollSensitivity]);
 
   const handleJigglerChange = (enabled: boolean) => {
     send("setJigglerState", { enabled }, resp => {
@@ -37,6 +49,22 @@ export default function SettingsKeyboardMouseRoute() {
     });
   };
 
+  const onScrollSensitivityChange = useCallback(
+    (e: React.ChangeEvent<HTMLSelectElement>) => {
+      const sensitivity = e.target.value as ScrollSensitivity;
+      send("setScrollSensitivity", { sensitivity }, resp => {
+        if ("error" in resp) {
+          notifications.error(
+            `Failed to set scroll sensitivity: ${resp.error.data || "Unknown error"}`,
+          );
+        }
+        notifications.success("Scroll sensitivity set successfully");
+        setScrollSensitivity(sensitivity);
+      });
+    },
+    [send, setScrollSensitivity],
+  );
+
   return (
     <div className="space-y-4">
       <SettingsPageHeader
@@ -54,6 +82,26 @@ export default function SettingsKeyboardMouseRoute() {
             onChange={e => setHideCursor(e.target.checked)}
           />
         </SettingsItem>
+        <SettingsItem
+          title="Scroll Sensitivity"
+          description="Adjust the scroll sensitivity"
+        >
+          <SelectMenuBasic
+            size="SM"
+            label=""
+            fullWidth
+            value={scrollSensitivity}
+            onChange={onScrollSensitivityChange}
+            options={
+              [
+                { label: "Low", value: "low" },
+                { label: "Default", value: "default" },
+                { label: "High", value: "high" },
+              ] as { label: string; value: ScrollSensitivity }[]
+            }
+          />
+        </SettingsItem>
+
         <SettingsItem
           title="Jiggler"
           description="Simulate movement of a computer mouse. Prevents sleep mode, standby mode or the screensaver from activating"
diff --git a/ui/src/routes/devices.$id.tsx b/ui/src/routes/devices.$id.tsx
index 5576d75..24a6428 100644
--- a/ui/src/routes/devices.$id.tsx
+++ b/ui/src/routes/devices.$id.tsx
@@ -1,8 +1,10 @@
 import { useCallback, useEffect, useRef, useState } from "react";
 import { cx } from "@/cva.config";
 import {
+  DeviceSettingsState,
   HidState,
   UpdateState,
+  useDeviceSettingsStore,
   useDeviceStore,
   useHidStore,
   useMountMediaStore,
@@ -428,18 +430,6 @@ export default function KvmIdRoute() {
     }
   }, [kvmTerminal, peerConnection, serialConsole]);
 
-  useEffect(() => {
-    kvmTerminal?.addEventListener("message", e => {
-      console.log(e.data);
-    });
-
-    return () => {
-      kvmTerminal?.removeEventListener("message", e => {
-        console.log(e.data);
-      });
-    };
-  }, [kvmTerminal]);
-
   const outlet = useOutlet();
   const location = useLocation();
   const onModalClose = useCallback(() => {
@@ -464,6 +454,21 @@ export default function KvmIdRoute() {
     });
   }, [appVersion, send, setAppVersion, setSystemVersion]);
 
+  const setScrollSensitivity = useDeviceSettingsStore(
+    state => state.setScrollSensitivity,
+  );
+
+  // Initialize device settings
+  useEffect(
+    function initializeDeviceSettings() {
+      send("getScrollSensitivity", {}, resp => {
+        if ("error" in resp) return;
+        setScrollSensitivity(resp.result as DeviceSettingsState["scrollSensitivity"]);
+      });
+    },
+    [send, setScrollSensitivity],
+  );
+
   return (
     <FeatureFlagProvider appVersion={appVersion}>
       {!outlet && otaState.updating && (
diff --git a/usb.go b/usb.go
index 8f413c7..1318d09 100644
--- a/usb.go
+++ b/usb.go
@@ -332,12 +332,15 @@ func rpcWheelReport(wheelY int8) error {
 		return errors.New("hid not initialized")
 	}
 
-	// Accumulate the wheelY value
-	accumulatedWheelY += float64(wheelY) / 8.0
+	// Accumulate the wheelY value with finer granularity
+	// Reduce divisor from 8.0 to a smaller value (e.g., 2.0 or 4.0)
+	accumulatedWheelY += float64(wheelY) / 4.0
 
-	// Only send a report if the accumulated value is significant
-	if abs(accumulatedWheelY) >= 1.0 {
-		scaledWheelY := int8(accumulatedWheelY)
+	// Lower the threshold for sending a report (0.25 instead of 1.0)
+	if abs(accumulatedWheelY) >= 0.25 {
+		// Scale the wheel value appropriately for the HID report
+		// The descriptor uses an 8-bit signed value (-127 to 127)
+		scaledWheelY := int8(accumulatedWheelY * 0.5) // Scale down to prevent too much scrolling
 
 		_, err := mouseHidFile.Write([]byte{
 			2,                  // Report ID 2
@@ -345,7 +348,7 @@ func rpcWheelReport(wheelY int8) error {
 		})
 
 		// Reset the accumulator, keeping any remainder
-		accumulatedWheelY -= float64(scaledWheelY)
+		accumulatedWheelY -= float64(scaledWheelY) / 0.5 // Adjust based on the scaling factor
 
 		resetUserInputTime()
 		return err