[{"data":1,"prerenderedAt":317},["ShallowReactive",2],{"i-lucide:menu":3,"i-simple-icons:github":8,"docs-\u002Fdocs\u002Farchitecture":10,"docs-nav":283,"i-lucide:book-open":301,"i-lucide:download":303,"i-lucide:shield-check":305,"i-lucide:layers":307,"i-lucide:wrench":309,"i-lucide:arrow-left":311,"i-lucide:arrow-right":313,"i-lucide:info":315},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"id":11,"title":12,"body":13,"description":274,"extension":275,"icon":276,"meta":277,"navigation":278,"order":264,"path":279,"seo":280,"stem":281,"__hash__":282},"docs\u002Fdocs\u002F3.architecture.md","Architecture",{"type":14,"value":15,"toc":263},"minimark",[16,20,25,29,36,47,54,57,61,72,81,85,104,107,111,114,204,207,211,218,221,232,236,246,253,257,260],[17,18,12],"h1",{"id":19},"architecture",[21,22,24],"h2",{"id":23},"the-decision-everything-follows-from","The decision everything follows from",[26,27,28],"p",{},"Logitech devices can be configured two ways, and choosing between them shapes\nthe entire product.",[26,30,31,35],{},[32,33,34],"strong",{},"Onboard configuration"," writes settings into the device's own flash. It\nsurvives reboots and works with no software running at all. But you are limited\nto the actions the firmware already implements, and inexpensive devices expose\nvery little onboard storage.",[26,37,38,41,42,46],{},[32,39,40],{},"Host-side interception"," uses HID++ ",[43,44,45],"em",{},"diversion",": the firmware is told to stop\nemitting a button's normal report and to send a notification instead, and the\napplication then synthesises whatever the user actually mapped. This allows\nunlimited actions, per-application behaviour, macros and gestures — but it\nrequires a running process, and diversion must be re-applied every time the\ndevice reconnects.",[26,48,49,50,53],{},"OpenLogi does ",[32,51,52],{},"both",", and prefers onboard wherever the firmware supports it.\nA DPI change is written onboard, so it persists with OpenLogi closed. A button\nmapped to \"open Figma\" must be host-side, because no firmware has that concept.",[26,55,56],{},"The interface tells you which is which, because the difference is visible in\nbehaviour: one survives a reboot without the app, the other does not.",[21,58,60],{"id":59},"layers","Layers",[62,63,68],"pre",{"className":64,"code":66,"language":67},[65],"language-text","┌──────────────────────────────────────────────────────────┐\n│  Desktop window (Vue 3 + Vite)        user session       │\n└───────────────┬──────────────────────────────────────────┘\n                │  IPC\n┌───────────────┴──────────────────────────────────────────┐\n│  device service  ─ hotplug watch, connection state       │\n│  button engine   ─ diversion, uinput emission            │\n│  profile engine  ─ persistence, per-app switching        │\n└───────────────┬──────────────────────────────────────────┘\n                │  hidpp\n┌───────────────┴──────────────────────────────────────────┐\n│  \u002Fdev\u002Fhidraw*  (uaccess ACL)        \u002Fdev\u002Fuinput          │\n└──────────────────────────────────────────────────────────┘\n","text",[69,70,66],"code",{"__ignoreMap":71},"",[26,73,74,75,80],{},"Nothing above runs as root. See ",[76,77,79],"a",{"href":78},"\u002Fdocs\u002Fpermissions","Permissions",".",[21,82,84],{"id":83},"finding-the-device","Finding the device",[26,86,87,88,91,92,95,96,99,100,103],{},"Logitech's HID++ endpoints are located by the ",[32,89,90],{},"shape of the HID report\ndescriptor"," rather than by matching product ids: the application looks for\nusage page ",[69,93,94],{},"0xFF00"," with report id ",[69,97,98],{},"0x10"," (7-byte short reports) or ",[69,101,102],{},"0x11","\n(20-byte long reports).",[26,105,106],{},"This matters because the same physical mouse presents completely different USB\nidentifiers depending on whether it is connected through a Bolt receiver, a\nUnifying receiver, Lightspeed, Bluetooth, or a cable. Matching on descriptor\nshape means all five paths resolve through one code path, and hardware released\nafter this was written still works.",[21,108,110],{"id":109},"capabilities-are-discovered-not-hard-coded","Capabilities are discovered, not hard-coded",[26,112,113],{},"On connection, the device is asked for its feature table. Panels in the\ninterface appear because the hardware reported the matching feature — never\nbecause a model name appeared on a list.",[115,116,117,130],"table",{},[118,119,120],"thead",{},[121,122,123,127],"tr",{},[124,125,126],"th",{},"Feature",[124,128,129],{},"Capability",[131,132,133,144,154,164,174,184,194],"tbody",{},[121,134,135,141],{},[136,137,138],"td",{},[69,139,140],{},"0x0003",[136,142,143],{},"Device information: firmware, serial",[121,145,146,151],{},[136,147,148],{},[69,149,150],{},"0x0005",[136,152,153],{},"Device name and kind",[121,155,156,161],{},[136,157,158],{},[69,159,160],{},"0x1000",[136,162,163],{},"Battery status and charging state",[121,165,166,171],{},[136,167,168],{},[69,169,170],{},"0x1001",[136,172,173],{},"Battery voltage, for older devices",[121,175,176,181],{},[136,177,178],{},[69,179,180],{},"0x1004",[136,182,183],{},"Unified battery reporting",[121,185,186,191],{},[136,187,188],{},[69,189,190],{},"0x1B04",[136,192,193],{},"Reprogrammable controls and diversion",[121,195,196,201],{},[136,197,198],{},[69,199,200],{},"0x2201",[136,202,203],{},"Adjustable DPI",[26,205,206],{},"The practical consequence: an unrecognised device is not unsupported. It shows\nexactly the controls it actually implements.",[21,208,210],{"id":209},"sharing-the-bus","Sharing the bus",[26,212,213,214,217],{},"HID++ 2.0 requests carry a 4-bit ",[32,215,216],{},"software id",", which the device echoes back\nin its reply. Several programs can therefore share one device without\nintercepting each other's responses — a reply is matched to the request that\nasked for it.",[26,219,220],{},"OpenLogi uses a software id distinct from the ones Solaar and fwupd use, so all\nthree can run simultaneously. This is why you do not have to uninstall Solaar\nto try OpenLogi.",[222,223,225],"callout",{"icon":224},"lucide:info",[26,226,227,228,231],{},"HID++ ",[32,229,230],{},"1.0"," has no software id — in that version the byte is data. Receiver\nnotifications are therefore matched by shape rather than by tag.",[21,233,235],{"id":234},"delivering-input","Delivering input",[26,237,238,239,241,242,245],{},"Diverted buttons arrive as ",[69,240,190],{}," notifications. The button engine maps each\nto its configured action and emits it through ",[69,243,244],{},"\u002Fdev\u002Fuinput",", a kernel virtual\ninput device.",[26,247,248,249,252],{},"Working below the display server is what makes one implementation serve both\nWayland and X11 — client-side injection such as ",[69,250,251],{},"XTEST"," does not work on\nWayland at all.",[21,254,256],{"id":255},"restoring-state","Restoring state",[26,258,259],{},"A diverted button is completely dead to the desktop: no click reaches any\napplication. Leaving one diverted after exit would look exactly like broken\nhardware.",[26,261,262],{},"OpenLogi therefore un-diverts every control on shutdown, from both a cleanup\nguard and a signal handler, and re-applies diversion whenever a device\nreconnects.",{"title":71,"searchDepth":264,"depth":264,"links":265},3,[266,268,269,270,271,272,273],{"id":23,"depth":267,"text":24},2,{"id":59,"depth":267,"text":60},{"id":83,"depth":267,"text":84},{"id":109,"depth":267,"text":110},{"id":209,"depth":267,"text":210},{"id":234,"depth":267,"text":235},{"id":255,"depth":267,"text":256},"Onboard versus host-side configuration, the HID++ protocol layer, and how OpenLogi shares the device bus with Solaar and fwupd.","md","lucide:layers",{},true,"\u002Fdocs\u002Farchitecture",{"title":12,"description":274},"docs\u002F3.architecture","cvvFvUYvieeiQK5AZ2zqaZf8kVFnrYJl0d5F7NwoLvk",[284,288,293,295,296],{"path":285,"title":286,"icon":287,"order":4},"\u002Fdocs","Introduction","lucide:book-open",{"path":289,"title":290,"icon":291,"order":292},"\u002Fdocs\u002Finstallation","Installation","lucide:download",1,{"path":78,"title":79,"icon":294,"order":267},"lucide:shield-check",{"path":279,"title":12,"icon":276,"order":264},{"path":297,"title":298,"icon":299,"order":300},"\u002Fdocs\u002Ftroubleshooting","Troubleshooting","lucide:wrench",4,{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":302},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 5v16m8.001-2A2 2 0 0 0 22 17V5a2 2 0 0 0-1.999-2L16 3.002A5 5 0 0 0 12 5a5 5 0 0 0-4-2H4a2 2 0 0 0-2 2v12a2 2 0 0 0 1.999 2H8a5 5 0 0 1 4 2a5 5 0 0 1 4-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":304},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12 15V3m9 12v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"\u002F>\u003Cpath d=\"m7 10l5 5l5-5\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":306},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\"\u002F>\u003Cpath d=\"m9 12l2 2l4-4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":308},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\"\u002F>\u003Cpath d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\"\u002F>\u003Cpath d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":310},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":312},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":314},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":316},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 16v-4m0-4h.01\"\u002F>\u003C\u002Fg>",1789403123747]