@openmouse/protocol 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (547) hide show
  1. package/CONTRIBUTING.md +167 -0
  2. package/README.md +89 -0
  3. package/dist/asus/index.d.ts +52 -0
  4. package/dist/asus/index.d.ts.map +1 -0
  5. package/dist/asus/index.js +248 -0
  6. package/dist/asus/index.js.map +1 -0
  7. package/dist/atk/index.d.ts +200 -0
  8. package/dist/atk/index.d.ts.map +1 -0
  9. package/dist/atk/index.js +480 -0
  10. package/dist/atk/index.js.map +1 -0
  11. package/dist/bitmouse/index.d.ts +284 -0
  12. package/dist/bitmouse/index.d.ts.map +1 -0
  13. package/dist/bitmouse/index.js +396 -0
  14. package/dist/bitmouse/index.js.map +1 -0
  15. package/dist/compx/codec.d.ts +31 -0
  16. package/dist/compx/codec.d.ts.map +1 -0
  17. package/dist/compx/codec.js +50 -0
  18. package/dist/compx/codec.js.map +1 -0
  19. package/dist/corsair/index.d.ts +147 -0
  20. package/dist/corsair/index.d.ts.map +1 -0
  21. package/dist/corsair/index.js +223 -0
  22. package/dist/corsair/index.js.map +1 -0
  23. package/dist/dareu/index.d.ts +136 -0
  24. package/dist/dareu/index.d.ts.map +1 -0
  25. package/dist/dareu/index.js +344 -0
  26. package/dist/dareu/index.js.map +1 -0
  27. package/dist/drivers/asus/hid.d.ts +29 -0
  28. package/dist/drivers/asus/hid.d.ts.map +1 -0
  29. package/dist/drivers/asus/hid.js +419 -0
  30. package/dist/drivers/asus/hid.js.map +1 -0
  31. package/dist/drivers/atk/bitmouse-hid.d.ts +80 -0
  32. package/dist/drivers/atk/bitmouse-hid.d.ts.map +1 -0
  33. package/dist/drivers/atk/bitmouse-hid.js +501 -0
  34. package/dist/drivers/atk/bitmouse-hid.js.map +1 -0
  35. package/dist/drivers/atk/hid.d.ts +163 -0
  36. package/dist/drivers/atk/hid.d.ts.map +1 -0
  37. package/dist/drivers/atk/hid.js +1368 -0
  38. package/dist/drivers/atk/hid.js.map +1 -0
  39. package/dist/drivers/atk/products.d.ts +13 -0
  40. package/dist/drivers/atk/products.d.ts.map +1 -0
  41. package/dist/drivers/atk/products.js +13 -0
  42. package/dist/drivers/atk/products.js.map +1 -0
  43. package/dist/drivers/attackshark/dpi.d.ts +41 -0
  44. package/dist/drivers/attackshark/dpi.d.ts.map +1 -0
  45. package/dist/drivers/attackshark/dpi.js +215 -0
  46. package/dist/drivers/attackshark/dpi.js.map +1 -0
  47. package/dist/drivers/attackshark/hid.d.ts +124 -0
  48. package/dist/drivers/attackshark/hid.d.ts.map +1 -0
  49. package/dist/drivers/attackshark/hid.js +728 -0
  50. package/dist/drivers/attackshark/hid.js.map +1 -0
  51. package/dist/drivers/corsair/hid.d.ts +70 -0
  52. package/dist/drivers/corsair/hid.d.ts.map +1 -0
  53. package/dist/drivers/corsair/hid.js +414 -0
  54. package/dist/drivers/corsair/hid.js.map +1 -0
  55. package/dist/drivers/dareu/hid.d.ts +59 -0
  56. package/dist/drivers/dareu/hid.d.ts.map +1 -0
  57. package/dist/drivers/dareu/hid.js +478 -0
  58. package/dist/drivers/dareu/hid.js.map +1 -0
  59. package/dist/drivers/endgame/egg-op1-hid.d.ts +107 -0
  60. package/dist/drivers/endgame/egg-op1-hid.d.ts.map +1 -0
  61. package/dist/drivers/endgame/egg-op1-hid.js +605 -0
  62. package/dist/drivers/endgame/egg-op1-hid.js.map +1 -0
  63. package/dist/drivers/endgame/egg-we-control.d.ts +42 -0
  64. package/dist/drivers/endgame/egg-we-control.d.ts.map +1 -0
  65. package/dist/drivers/endgame/egg-we-control.js +87 -0
  66. package/dist/drivers/endgame/egg-we-control.js.map +1 -0
  67. package/dist/drivers/endgame/egg-we-hid.d.ts +58 -0
  68. package/dist/drivers/endgame/egg-we-hid.d.ts.map +1 -0
  69. package/dist/drivers/endgame/egg-we-hid.js +514 -0
  70. package/dist/drivers/endgame/egg-we-hid.js.map +1 -0
  71. package/dist/drivers/fantech/hid.d.ts +106 -0
  72. package/dist/drivers/fantech/hid.d.ts.map +1 -0
  73. package/dist/drivers/fantech/hid.js +295 -0
  74. package/dist/drivers/fantech/hid.js.map +1 -0
  75. package/dist/drivers/finalmouse/hid.d.ts +31 -0
  76. package/dist/drivers/finalmouse/hid.d.ts.map +1 -0
  77. package/dist/drivers/finalmouse/hid.js +181 -0
  78. package/dist/drivers/finalmouse/hid.js.map +1 -0
  79. package/dist/drivers/gearhub/hid.d.ts +191 -0
  80. package/dist/drivers/gearhub/hid.d.ts.map +1 -0
  81. package/dist/drivers/gearhub/hid.js +542 -0
  82. package/dist/drivers/gearhub/hid.js.map +1 -0
  83. package/dist/drivers/glorious/classic-hid.d.ts +62 -0
  84. package/dist/drivers/glorious/classic-hid.d.ts.map +1 -0
  85. package/dist/drivers/glorious/classic-hid.js +326 -0
  86. package/dist/drivers/glorious/classic-hid.js.map +1 -0
  87. package/dist/drivers/glorious/hid.d.ts +39 -0
  88. package/dist/drivers/glorious/hid.d.ts.map +1 -0
  89. package/dist/drivers/glorious/hid.js +203 -0
  90. package/dist/drivers/glorious/hid.js.map +1 -0
  91. package/dist/drivers/gwolves/hid.d.ts +27 -0
  92. package/dist/drivers/gwolves/hid.d.ts.map +1 -0
  93. package/dist/drivers/gwolves/hid.js +225 -0
  94. package/dist/drivers/gwolves/hid.js.map +1 -0
  95. package/dist/drivers/gwolves/products.d.ts +17 -0
  96. package/dist/drivers/gwolves/products.d.ts.map +1 -0
  97. package/dist/drivers/gwolves/products.js +58 -0
  98. package/dist/drivers/gwolves/products.js.map +1 -0
  99. package/dist/drivers/hyperx/hid.d.ts +59 -0
  100. package/dist/drivers/hyperx/hid.d.ts.map +1 -0
  101. package/dist/drivers/hyperx/hid.js +229 -0
  102. package/dist/drivers/hyperx/hid.js.map +1 -0
  103. package/dist/drivers/incott/hid.d.ts +513 -0
  104. package/dist/drivers/incott/hid.d.ts.map +1 -0
  105. package/dist/drivers/incott/hid.js +1173 -0
  106. package/dist/drivers/incott/hid.js.map +1 -0
  107. package/dist/drivers/index.d.ts +5 -0
  108. package/dist/drivers/index.d.ts.map +1 -0
  109. package/dist/drivers/index.js +5 -0
  110. package/dist/drivers/index.js.map +1 -0
  111. package/dist/drivers/keychron/m6-hid.d.ts +81 -0
  112. package/dist/drivers/keychron/m6-hid.d.ts.map +1 -0
  113. package/dist/drivers/keychron/m6-hid.js +486 -0
  114. package/dist/drivers/keychron/m6-hid.js.map +1 -0
  115. package/dist/drivers/keychron/nape-hid.d.ts +60 -0
  116. package/dist/drivers/keychron/nape-hid.d.ts.map +1 -0
  117. package/dist/drivers/keychron/nape-hid.js +432 -0
  118. package/dist/drivers/keychron/nape-hid.js.map +1 -0
  119. package/dist/drivers/ksnake/hid.d.ts +74 -0
  120. package/dist/drivers/ksnake/hid.d.ts.map +1 -0
  121. package/dist/drivers/ksnake/hid.js +368 -0
  122. package/dist/drivers/ksnake/hid.js.map +1 -0
  123. package/dist/drivers/lamzu/hid.d.ts +58 -0
  124. package/dist/drivers/lamzu/hid.d.ts.map +1 -0
  125. package/dist/drivers/lamzu/hid.js +414 -0
  126. package/dist/drivers/lamzu/hid.js.map +1 -0
  127. package/dist/drivers/lamzu-atlantis/hid.d.ts +148 -0
  128. package/dist/drivers/lamzu-atlantis/hid.d.ts.map +1 -0
  129. package/dist/drivers/lamzu-atlantis/hid.js +587 -0
  130. package/dist/drivers/lamzu-atlantis/hid.js.map +1 -0
  131. package/dist/drivers/logitech/bolt.d.ts +41 -0
  132. package/dist/drivers/logitech/bolt.d.ts.map +1 -0
  133. package/dist/drivers/logitech/bolt.js +105 -0
  134. package/dist/drivers/logitech/bolt.js.map +1 -0
  135. package/dist/drivers/logitech/hidpp.d.ts +525 -0
  136. package/dist/drivers/logitech/hidpp.d.ts.map +1 -0
  137. package/dist/drivers/logitech/hidpp.js +2774 -0
  138. package/dist/drivers/logitech/hidpp.js.map +1 -0
  139. package/dist/drivers/logitech/mode-status.d.ts +53 -0
  140. package/dist/drivers/logitech/mode-status.d.ts.map +1 -0
  141. package/dist/drivers/logitech/mode-status.js +52 -0
  142. package/dist/drivers/logitech/mode-status.js.map +1 -0
  143. package/dist/drivers/logitech/onboard-profiles.d.ts +298 -0
  144. package/dist/drivers/logitech/onboard-profiles.d.ts.map +1 -0
  145. package/dist/drivers/logitech/onboard-profiles.js +965 -0
  146. package/dist/drivers/logitech/onboard-profiles.js.map +1 -0
  147. package/dist/drivers/logitech/rgb-effects.d.ts +20 -0
  148. package/dist/drivers/logitech/rgb-effects.d.ts.map +1 -0
  149. package/dist/drivers/logitech/rgb-effects.js +93 -0
  150. package/dist/drivers/logitech/rgb-effects.js.map +1 -0
  151. package/dist/drivers/mchose/a5-gen1-hid.d.ts +36 -0
  152. package/dist/drivers/mchose/a5-gen1-hid.d.ts.map +1 -0
  153. package/dist/drivers/mchose/a5-gen1-hid.js +219 -0
  154. package/dist/drivers/mchose/a5-gen1-hid.js.map +1 -0
  155. package/dist/drivers/mchose/dock-hid.d.ts +26 -0
  156. package/dist/drivers/mchose/dock-hid.d.ts.map +1 -0
  157. package/dist/drivers/mchose/dock-hid.js +176 -0
  158. package/dist/drivers/mchose/dock-hid.js.map +1 -0
  159. package/dist/drivers/mchose/hid.d.ts +118 -0
  160. package/dist/drivers/mchose/hid.d.ts.map +1 -0
  161. package/dist/drivers/mchose/hid.js +550 -0
  162. package/dist/drivers/mchose/hid.js.map +1 -0
  163. package/dist/drivers/mchose/v3-hid.d.ts +109 -0
  164. package/dist/drivers/mchose/v3-hid.d.ts.map +1 -0
  165. package/dist/drivers/mchose/v3-hid.js +572 -0
  166. package/dist/drivers/mchose/v3-hid.js.map +1 -0
  167. package/dist/drivers/microsoft/hid.d.ts +25 -0
  168. package/dist/drivers/microsoft/hid.d.ts.map +1 -0
  169. package/dist/drivers/microsoft/hid.js +247 -0
  170. package/dist/drivers/microsoft/hid.js.map +1 -0
  171. package/dist/drivers/moddo/hid.d.ts +31 -0
  172. package/dist/drivers/moddo/hid.d.ts.map +1 -0
  173. package/dist/drivers/moddo/hid.js +154 -0
  174. package/dist/drivers/moddo/hid.js.map +1 -0
  175. package/dist/drivers/mouse-types.d.ts +388 -0
  176. package/dist/drivers/mouse-types.d.ts.map +1 -0
  177. package/dist/drivers/mouse-types.js +2 -0
  178. package/dist/drivers/mouse-types.js.map +1 -0
  179. package/dist/drivers/ninjutso/hid.d.ts +62 -0
  180. package/dist/drivers/ninjutso/hid.d.ts.map +1 -0
  181. package/dist/drivers/ninjutso/hid.js +680 -0
  182. package/dist/drivers/ninjutso/hid.js.map +1 -0
  183. package/dist/drivers/orbital/hid.d.ts +24 -0
  184. package/dist/drivers/orbital/hid.d.ts.map +1 -0
  185. package/dist/drivers/orbital/hid.js +85 -0
  186. package/dist/drivers/orbital/hid.js.map +1 -0
  187. package/dist/drivers/orbital/host-protocol.d.ts +59 -0
  188. package/dist/drivers/orbital/host-protocol.d.ts.map +1 -0
  189. package/dist/drivers/orbital/host-protocol.js +884 -0
  190. package/dist/drivers/orbital/host-protocol.js.map +1 -0
  191. package/dist/drivers/pulsar/pulsar-hid.d.ts +63 -0
  192. package/dist/drivers/pulsar/pulsar-hid.d.ts.map +1 -0
  193. package/dist/drivers/pulsar/pulsar-hid.js +381 -0
  194. package/dist/drivers/pulsar/pulsar-hid.js.map +1 -0
  195. package/dist/drivers/pulsar/pulsar-pro-hid.d.ts +46 -0
  196. package/dist/drivers/pulsar/pulsar-pro-hid.d.ts.map +1 -0
  197. package/dist/drivers/pulsar/pulsar-pro-hid.js +343 -0
  198. package/dist/drivers/pulsar/pulsar-pro-hid.js.map +1 -0
  199. package/dist/drivers/pulsar/pulsar-xs1-hid.d.ts +40 -0
  200. package/dist/drivers/pulsar/pulsar-xs1-hid.d.ts.map +1 -0
  201. package/dist/drivers/pulsar/pulsar-xs1-hid.js +251 -0
  202. package/dist/drivers/pulsar/pulsar-xs1-hid.js.map +1 -0
  203. package/dist/drivers/rawm/hid.d.ts +29 -0
  204. package/dist/drivers/rawm/hid.d.ts.map +1 -0
  205. package/dist/drivers/rawm/hid.js +210 -0
  206. package/dist/drivers/rawm/hid.js.map +1 -0
  207. package/dist/drivers/razer/cobra-hid.d.ts +63 -0
  208. package/dist/drivers/razer/cobra-hid.d.ts.map +1 -0
  209. package/dist/drivers/razer/cobra-hid.js +282 -0
  210. package/dist/drivers/razer/cobra-hid.js.map +1 -0
  211. package/dist/drivers/razer/hid-open.d.ts +13 -0
  212. package/dist/drivers/razer/hid-open.d.ts.map +1 -0
  213. package/dist/drivers/razer/hid-open.js +29 -0
  214. package/dist/drivers/razer/hid-open.js.map +1 -0
  215. package/dist/drivers/razer/hid.d.ts +231 -0
  216. package/dist/drivers/razer/hid.d.ts.map +1 -0
  217. package/dist/drivers/razer/hid.js +772 -0
  218. package/dist/drivers/razer/hid.js.map +1 -0
  219. package/dist/drivers/razer/viper-hid.d.ts +33 -0
  220. package/dist/drivers/razer/viper-hid.d.ts.map +1 -0
  221. package/dist/drivers/razer/viper-hid.js +177 -0
  222. package/dist/drivers/razer/viper-hid.js.map +1 -0
  223. package/dist/drivers/razer/viper-mini-hid.d.ts +58 -0
  224. package/dist/drivers/razer/viper-mini-hid.d.ts.map +1 -0
  225. package/dist/drivers/razer/viper-mini-hid.js +273 -0
  226. package/dist/drivers/razer/viper-mini-hid.js.map +1 -0
  227. package/dist/drivers/razer/viper-v4-pro-hid.d.ts +26 -0
  228. package/dist/drivers/razer/viper-v4-pro-hid.d.ts.map +1 -0
  229. package/dist/drivers/razer/viper-v4-pro-hid.js +154 -0
  230. package/dist/drivers/razer/viper-v4-pro-hid.js.map +1 -0
  231. package/dist/drivers/registry.d.ts +70 -0
  232. package/dist/drivers/registry.d.ts.map +1 -0
  233. package/dist/drivers/registry.js +146 -0
  234. package/dist/drivers/registry.js.map +1 -0
  235. package/dist/drivers/steelseries/aerox3-hid.d.ts +53 -0
  236. package/dist/drivers/steelseries/aerox3-hid.d.ts.map +1 -0
  237. package/dist/drivers/steelseries/aerox3-hid.js +172 -0
  238. package/dist/drivers/steelseries/aerox3-hid.js.map +1 -0
  239. package/dist/drivers/steelseries/aerox5-hid.d.ts +54 -0
  240. package/dist/drivers/steelseries/aerox5-hid.d.ts.map +1 -0
  241. package/dist/drivers/steelseries/aerox5-hid.js +173 -0
  242. package/dist/drivers/steelseries/aerox5-hid.js.map +1 -0
  243. package/dist/drivers/steelseries/aerox5-wireless-hid.d.ts +69 -0
  244. package/dist/drivers/steelseries/aerox5-wireless-hid.d.ts.map +1 -0
  245. package/dist/drivers/steelseries/aerox5-wireless-hid.js +234 -0
  246. package/dist/drivers/steelseries/aerox5-wireless-hid.js.map +1 -0
  247. package/dist/drivers/steelseries/aerox9-wireless-hid.d.ts +70 -0
  248. package/dist/drivers/steelseries/aerox9-wireless-hid.d.ts.map +1 -0
  249. package/dist/drivers/steelseries/aerox9-wireless-hid.js +227 -0
  250. package/dist/drivers/steelseries/aerox9-wireless-hid.js.map +1 -0
  251. package/dist/drivers/steelseries/hid.d.ts +48 -0
  252. package/dist/drivers/steelseries/hid.d.ts.map +1 -0
  253. package/dist/drivers/steelseries/hid.js +157 -0
  254. package/dist/drivers/steelseries/hid.js.map +1 -0
  255. package/dist/drivers/steelseries/prime-mini-wireless-hid.d.ts +62 -0
  256. package/dist/drivers/steelseries/prime-mini-wireless-hid.d.ts.map +1 -0
  257. package/dist/drivers/steelseries/prime-mini-wireless-hid.js +215 -0
  258. package/dist/drivers/steelseries/prime-mini-wireless-hid.js.map +1 -0
  259. package/dist/drivers/steelseries/prime-plus-hid.d.ts +51 -0
  260. package/dist/drivers/steelseries/prime-plus-hid.d.ts.map +1 -0
  261. package/dist/drivers/steelseries/prime-plus-hid.js +150 -0
  262. package/dist/drivers/steelseries/prime-plus-hid.js.map +1 -0
  263. package/dist/drivers/steelseries/rival3-wireless-hid.d.ts +61 -0
  264. package/dist/drivers/steelseries/rival3-wireless-hid.d.ts.map +1 -0
  265. package/dist/drivers/steelseries/rival3-wireless-hid.js +185 -0
  266. package/dist/drivers/steelseries/rival3-wireless-hid.js.map +1 -0
  267. package/dist/drivers/steelseries/rival310-hid.d.ts +59 -0
  268. package/dist/drivers/steelseries/rival310-hid.d.ts.map +1 -0
  269. package/dist/drivers/steelseries/rival310-hid.js +182 -0
  270. package/dist/drivers/steelseries/rival310-hid.js.map +1 -0
  271. package/dist/drivers/steelseries/rival650-hid.d.ts +68 -0
  272. package/dist/drivers/steelseries/rival650-hid.d.ts.map +1 -0
  273. package/dist/drivers/steelseries/rival650-hid.js +209 -0
  274. package/dist/drivers/steelseries/rival650-hid.js.map +1 -0
  275. package/dist/drivers/steelseries/sensei-ten-hid.d.ts +62 -0
  276. package/dist/drivers/steelseries/sensei-ten-hid.d.ts.map +1 -0
  277. package/dist/drivers/steelseries/sensei-ten-hid.js +186 -0
  278. package/dist/drivers/steelseries/sensei-ten-hid.js.map +1 -0
  279. package/dist/drivers/teevolution/hid.d.ts +82 -0
  280. package/dist/drivers/teevolution/hid.d.ts.map +1 -0
  281. package/dist/drivers/teevolution/hid.js +607 -0
  282. package/dist/drivers/teevolution/hid.js.map +1 -0
  283. package/dist/drivers/vendors.d.ts +254 -0
  284. package/dist/drivers/vendors.d.ts.map +1 -0
  285. package/dist/drivers/vendors.js +587 -0
  286. package/dist/drivers/vendors.js.map +1 -0
  287. package/dist/drivers/vgn/hid.d.ts +33 -0
  288. package/dist/drivers/vgn/hid.d.ts.map +1 -0
  289. package/dist/drivers/vgn/hid.js +213 -0
  290. package/dist/drivers/vgn/hid.js.map +1 -0
  291. package/dist/drivers/wallhack/keyboard-hid.d.ts +28 -0
  292. package/dist/drivers/wallhack/keyboard-hid.d.ts.map +1 -0
  293. package/dist/drivers/wallhack/keyboard-hid.js +80 -0
  294. package/dist/drivers/wallhack/keyboard-hid.js.map +1 -0
  295. package/dist/drivers/wallhack/mouse-hid.d.ts +45 -0
  296. package/dist/drivers/wallhack/mouse-hid.d.ts.map +1 -0
  297. package/dist/drivers/wallhack/mouse-hid.js +288 -0
  298. package/dist/drivers/wallhack/mouse-hid.js.map +1 -0
  299. package/dist/drivers/webhid.d.ts +59 -0
  300. package/dist/drivers/webhid.d.ts.map +1 -0
  301. package/dist/drivers/webhid.js +2 -0
  302. package/dist/drivers/webhid.js.map +1 -0
  303. package/dist/drivers/wlmouse/hid.d.ts +81 -0
  304. package/dist/drivers/wlmouse/hid.d.ts.map +1 -0
  305. package/dist/drivers/wlmouse/hid.js +576 -0
  306. package/dist/drivers/wlmouse/hid.js.map +1 -0
  307. package/dist/drivers/wooting/hid.d.ts +86 -0
  308. package/dist/drivers/wooting/hid.d.ts.map +1 -0
  309. package/dist/drivers/wooting/hid.js +320 -0
  310. package/dist/drivers/wooting/hid.js.map +1 -0
  311. package/dist/drivers/zaunkoenig/hid.d.ts +31 -0
  312. package/dist/drivers/zaunkoenig/hid.d.ts.map +1 -0
  313. package/dist/drivers/zaunkoenig/hid.js +162 -0
  314. package/dist/drivers/zaunkoenig/hid.js.map +1 -0
  315. package/dist/endgame-gear/op1.d.ts +165 -0
  316. package/dist/endgame-gear/op1.d.ts.map +1 -0
  317. package/dist/endgame-gear/op1.js +384 -0
  318. package/dist/endgame-gear/op1.js.map +1 -0
  319. package/dist/endgame-gear/wireless.d.ts +93 -0
  320. package/dist/endgame-gear/wireless.d.ts.map +1 -0
  321. package/dist/endgame-gear/wireless.js +242 -0
  322. package/dist/endgame-gear/wireless.js.map +1 -0
  323. package/dist/fantech/index.d.ts +9 -0
  324. package/dist/fantech/index.d.ts.map +1 -0
  325. package/dist/fantech/index.js +11 -0
  326. package/dist/fantech/index.js.map +1 -0
  327. package/dist/finalmouse/index.d.ts +41 -0
  328. package/dist/finalmouse/index.d.ts.map +1 -0
  329. package/dist/finalmouse/index.js +106 -0
  330. package/dist/finalmouse/index.js.map +1 -0
  331. package/dist/gearhub/index.d.ts +210 -0
  332. package/dist/gearhub/index.d.ts.map +1 -0
  333. package/dist/gearhub/index.js +282 -0
  334. package/dist/gearhub/index.js.map +1 -0
  335. package/dist/glorious/index.d.ts +89 -0
  336. package/dist/glorious/index.d.ts.map +1 -0
  337. package/dist/glorious/index.js +236 -0
  338. package/dist/glorious/index.js.map +1 -0
  339. package/dist/glorious-classic/index.d.ts +103 -0
  340. package/dist/glorious-classic/index.d.ts.map +1 -0
  341. package/dist/glorious-classic/index.js +304 -0
  342. package/dist/glorious-classic/index.js.map +1 -0
  343. package/dist/gwolves/index.d.ts +82 -0
  344. package/dist/gwolves/index.d.ts.map +1 -0
  345. package/dist/gwolves/index.js +197 -0
  346. package/dist/gwolves/index.js.map +1 -0
  347. package/dist/hyperx/index.d.ts +181 -0
  348. package/dist/hyperx/index.d.ts.map +1 -0
  349. package/dist/hyperx/index.js +303 -0
  350. package/dist/hyperx/index.js.map +1 -0
  351. package/dist/incott/index.d.ts +1067 -0
  352. package/dist/incott/index.d.ts.map +1 -0
  353. package/dist/incott/index.js +1482 -0
  354. package/dist/incott/index.js.map +1 -0
  355. package/dist/index.d.ts +30 -0
  356. package/dist/index.d.ts.map +1 -0
  357. package/dist/index.js +30 -0
  358. package/dist/index.js.map +1 -0
  359. package/dist/keychron/index.d.ts +194 -0
  360. package/dist/keychron/index.d.ts.map +1 -0
  361. package/dist/keychron/index.js +341 -0
  362. package/dist/keychron/index.js.map +1 -0
  363. package/dist/ksnake/index.d.ts +157 -0
  364. package/dist/ksnake/index.d.ts.map +1 -0
  365. package/dist/ksnake/index.js +314 -0
  366. package/dist/ksnake/index.js.map +1 -0
  367. package/dist/lamzu/atlantis.d.ts +237 -0
  368. package/dist/lamzu/atlantis.d.ts.map +1 -0
  369. package/dist/lamzu/atlantis.js +263 -0
  370. package/dist/lamzu/atlantis.js.map +1 -0
  371. package/dist/lamzu/index.d.ts +60 -0
  372. package/dist/lamzu/index.d.ts.map +1 -0
  373. package/dist/lamzu/index.js +86 -0
  374. package/dist/lamzu/index.js.map +1 -0
  375. package/dist/logitech/controls.d.ts +138 -0
  376. package/dist/logitech/controls.d.ts.map +1 -0
  377. package/dist/logitech/controls.js +184 -0
  378. package/dist/logitech/controls.js.map +1 -0
  379. package/dist/logitech/friendly-name.d.ts +50 -0
  380. package/dist/logitech/friendly-name.d.ts.map +1 -0
  381. package/dist/logitech/friendly-name.js +74 -0
  382. package/dist/logitech/friendly-name.js.map +1 -0
  383. package/dist/logitech/haptics.d.ts +97 -0
  384. package/dist/logitech/haptics.d.ts.map +1 -0
  385. package/dist/logitech/haptics.js +116 -0
  386. package/dist/logitech/haptics.js.map +1 -0
  387. package/dist/logitech/hosts.d.ts +55 -0
  388. package/dist/logitech/hosts.d.ts.map +1 -0
  389. package/dist/logitech/hosts.js +80 -0
  390. package/dist/logitech/hosts.js.map +1 -0
  391. package/dist/logitech/index.d.ts +127 -0
  392. package/dist/logitech/index.d.ts.map +1 -0
  393. package/dist/logitech/index.js +233 -0
  394. package/dist/logitech/index.js.map +1 -0
  395. package/dist/logitech/wheel.d.ts +117 -0
  396. package/dist/logitech/wheel.d.ts.map +1 -0
  397. package/dist/logitech/wheel.js +133 -0
  398. package/dist/logitech/wheel.js.map +1 -0
  399. package/dist/mchose/a5-gen1.d.ts +38 -0
  400. package/dist/mchose/a5-gen1.d.ts.map +1 -0
  401. package/dist/mchose/a5-gen1.js +60 -0
  402. package/dist/mchose/a5-gen1.js.map +1 -0
  403. package/dist/mchose/buttons.d.ts +66 -0
  404. package/dist/mchose/buttons.d.ts.map +1 -0
  405. package/dist/mchose/buttons.js +184 -0
  406. package/dist/mchose/buttons.js.map +1 -0
  407. package/dist/mchose/dock.d.ts +77 -0
  408. package/dist/mchose/dock.d.ts.map +1 -0
  409. package/dist/mchose/dock.js +133 -0
  410. package/dist/mchose/dock.js.map +1 -0
  411. package/dist/mchose/index.d.ts +299 -0
  412. package/dist/mchose/index.d.ts.map +1 -0
  413. package/dist/mchose/index.js +429 -0
  414. package/dist/mchose/index.js.map +1 -0
  415. package/dist/mchose/v3-buttons.d.ts +64 -0
  416. package/dist/mchose/v3-buttons.d.ts.map +1 -0
  417. package/dist/mchose/v3-buttons.js +258 -0
  418. package/dist/mchose/v3-buttons.js.map +1 -0
  419. package/dist/mchose/v3.d.ts +380 -0
  420. package/dist/mchose/v3.d.ts.map +1 -0
  421. package/dist/mchose/v3.js +608 -0
  422. package/dist/mchose/v3.js.map +1 -0
  423. package/dist/microsoft/index.d.ts +19 -0
  424. package/dist/microsoft/index.d.ts.map +1 -0
  425. package/dist/microsoft/index.js +22 -0
  426. package/dist/microsoft/index.js.map +1 -0
  427. package/dist/moddo/index.d.ts +72 -0
  428. package/dist/moddo/index.d.ts.map +1 -0
  429. package/dist/moddo/index.js +147 -0
  430. package/dist/moddo/index.js.map +1 -0
  431. package/dist/ninjutso/index.d.ts +74 -0
  432. package/dist/ninjutso/index.d.ts.map +1 -0
  433. package/dist/ninjutso/index.js +133 -0
  434. package/dist/ninjutso/index.js.map +1 -0
  435. package/dist/orbital/index.d.ts +14 -0
  436. package/dist/orbital/index.d.ts.map +1 -0
  437. package/dist/orbital/index.js +19 -0
  438. package/dist/orbital/index.js.map +1 -0
  439. package/dist/pulsar/index.d.ts +81 -0
  440. package/dist/pulsar/index.d.ts.map +1 -0
  441. package/dist/pulsar/index.js +185 -0
  442. package/dist/pulsar/index.js.map +1 -0
  443. package/dist/rawm/index.d.ts +55 -0
  444. package/dist/rawm/index.d.ts.map +1 -0
  445. package/dist/rawm/index.js +229 -0
  446. package/dist/rawm/index.js.map +1 -0
  447. package/dist/razer/codec.d.ts +504 -0
  448. package/dist/razer/codec.d.ts.map +1 -0
  449. package/dist/razer/codec.js +648 -0
  450. package/dist/razer/codec.js.map +1 -0
  451. package/dist/razer/devices.d.ts +156 -0
  452. package/dist/razer/devices.d.ts.map +1 -0
  453. package/dist/razer/devices.js +540 -0
  454. package/dist/razer/devices.js.map +1 -0
  455. package/dist/razer/index.d.ts +2 -0
  456. package/dist/razer/index.d.ts.map +1 -0
  457. package/dist/razer/index.js +2 -0
  458. package/dist/razer/index.js.map +1 -0
  459. package/dist/razer/v4.d.ts +19 -0
  460. package/dist/razer/v4.d.ts.map +1 -0
  461. package/dist/razer/v4.js +51 -0
  462. package/dist/razer/v4.js.map +1 -0
  463. package/dist/steelseries/aerox3.d.ts +236 -0
  464. package/dist/steelseries/aerox3.d.ts.map +1 -0
  465. package/dist/steelseries/aerox3.js +311 -0
  466. package/dist/steelseries/aerox3.js.map +1 -0
  467. package/dist/steelseries/aerox5-wireless.d.ts +300 -0
  468. package/dist/steelseries/aerox5-wireless.d.ts.map +1 -0
  469. package/dist/steelseries/aerox5-wireless.js +389 -0
  470. package/dist/steelseries/aerox5-wireless.js.map +1 -0
  471. package/dist/steelseries/aerox5.d.ts +228 -0
  472. package/dist/steelseries/aerox5.d.ts.map +1 -0
  473. package/dist/steelseries/aerox5.js +294 -0
  474. package/dist/steelseries/aerox5.js.map +1 -0
  475. package/dist/steelseries/aerox9-wireless.d.ts +213 -0
  476. package/dist/steelseries/aerox9-wireless.d.ts.map +1 -0
  477. package/dist/steelseries/aerox9-wireless.js +305 -0
  478. package/dist/steelseries/aerox9-wireless.js.map +1 -0
  479. package/dist/steelseries/devices.d.ts +82 -0
  480. package/dist/steelseries/devices.d.ts.map +1 -0
  481. package/dist/steelseries/devices.js +310 -0
  482. package/dist/steelseries/devices.js.map +1 -0
  483. package/dist/steelseries/index.d.ts +13 -0
  484. package/dist/steelseries/index.d.ts.map +1 -0
  485. package/dist/steelseries/index.js +13 -0
  486. package/dist/steelseries/index.js.map +1 -0
  487. package/dist/steelseries/prime-mini-wireless.d.ts +253 -0
  488. package/dist/steelseries/prime-mini-wireless.d.ts.map +1 -0
  489. package/dist/steelseries/prime-mini-wireless.js +351 -0
  490. package/dist/steelseries/prime-mini-wireless.js.map +1 -0
  491. package/dist/steelseries/prime-plus.d.ts +179 -0
  492. package/dist/steelseries/prime-plus.d.ts.map +1 -0
  493. package/dist/steelseries/prime-plus.js +275 -0
  494. package/dist/steelseries/prime-plus.js.map +1 -0
  495. package/dist/steelseries/rival3-wireless.d.ts +222 -0
  496. package/dist/steelseries/rival3-wireless.d.ts.map +1 -0
  497. package/dist/steelseries/rival3-wireless.js +308 -0
  498. package/dist/steelseries/rival3-wireless.js.map +1 -0
  499. package/dist/steelseries/rival3.d.ts +99 -0
  500. package/dist/steelseries/rival3.d.ts.map +1 -0
  501. package/dist/steelseries/rival3.js +147 -0
  502. package/dist/steelseries/rival3.js.map +1 -0
  503. package/dist/steelseries/rival310.d.ts +230 -0
  504. package/dist/steelseries/rival310.d.ts.map +1 -0
  505. package/dist/steelseries/rival310.js +322 -0
  506. package/dist/steelseries/rival310.js.map +1 -0
  507. package/dist/steelseries/rival650.d.ts +215 -0
  508. package/dist/steelseries/rival650.d.ts.map +1 -0
  509. package/dist/steelseries/rival650.js +284 -0
  510. package/dist/steelseries/rival650.js.map +1 -0
  511. package/dist/steelseries/sensei-ten.d.ts +283 -0
  512. package/dist/steelseries/sensei-ten.d.ts.map +1 -0
  513. package/dist/steelseries/sensei-ten.js +389 -0
  514. package/dist/steelseries/sensei-ten.js.map +1 -0
  515. package/dist/teevolution/index.d.ts +211 -0
  516. package/dist/teevolution/index.d.ts.map +1 -0
  517. package/dist/teevolution/index.js +458 -0
  518. package/dist/teevolution/index.js.map +1 -0
  519. package/dist/valkyrie/index.d.ts +19 -0
  520. package/dist/valkyrie/index.d.ts.map +1 -0
  521. package/dist/valkyrie/index.js +43 -0
  522. package/dist/valkyrie/index.js.map +1 -0
  523. package/dist/valkyrie/settings.d.ts +28 -0
  524. package/dist/valkyrie/settings.d.ts.map +1 -0
  525. package/dist/valkyrie/settings.js +84 -0
  526. package/dist/valkyrie/settings.js.map +1 -0
  527. package/dist/vgn/index.d.ts +59 -0
  528. package/dist/vgn/index.d.ts.map +1 -0
  529. package/dist/vgn/index.js +165 -0
  530. package/dist/vgn/index.js.map +1 -0
  531. package/dist/wallhack/index.d.ts +165 -0
  532. package/dist/wallhack/index.d.ts.map +1 -0
  533. package/dist/wallhack/index.js +226 -0
  534. package/dist/wallhack/index.js.map +1 -0
  535. package/dist/wlmouse/index.d.ts +4 -0
  536. package/dist/wlmouse/index.d.ts.map +1 -0
  537. package/dist/wlmouse/index.js +7 -0
  538. package/dist/wlmouse/index.js.map +1 -0
  539. package/dist/wooting/index.d.ts +225 -0
  540. package/dist/wooting/index.d.ts.map +1 -0
  541. package/dist/wooting/index.js +296 -0
  542. package/dist/wooting/index.js.map +1 -0
  543. package/dist/zaunkoenig/index.d.ts +49 -0
  544. package/dist/zaunkoenig/index.d.ts.map +1 -0
  545. package/dist/zaunkoenig/index.js +127 -0
  546. package/dist/zaunkoenig/index.js.map +1 -0
  547. package/package.json +193 -0
@@ -0,0 +1,1067 @@
1
+ /**
2
+ * Incott HID protocol — transport-independent codec.
3
+ *
4
+ * Derived from IncottHIDApp (`romkazor/IncottHIDApp`, MIT licensed; this
5
+ * module reuses its protocol knowledge, not its code) and verified against
6
+ * an "incott 8K wireless mouse" (093A:522C) on real hardware. Ported from
7
+ * IncottHub (https://github.com/vladidraganov/IncottHub), which documents the
8
+ * verification in `docs/superpowers/specs/2026-09-07-incotthub-design.md`
9
+ * sections 4, 5, 8 and 13.
10
+ *
11
+ * DPI and battery were corrected on 2026-09-07 against a second, higher-trust
12
+ * source: the owner instrumented Incott's own WebHID configurator
13
+ * (incott.net/mouse/, hooking HIDDevice.prototype.sendFeatureReport /
14
+ * receiveFeatureReport) and captured real traffic to a G23V2Pro. That capture
15
+ * is ground truth and disproved two assumptions this driver inherited from
16
+ * IncottHIDApp — see `captures/incott-8k-wireless/vendor-tool-session.hex`
17
+ * and `docs/incott-testing.md`.
18
+ *
19
+ * A THIRD round of verification on 2026-09-08 used node-hid directly against
20
+ * an "incott 8K wireless mouse" and, uniquely among the capture sessions
21
+ * above, performed real WRITES and read every one back before restoring the
22
+ * original value. It fixed the DPI stage-index write bug (see
23
+ * `INCOTT_DPI_STAGE_COUNT`), confirmed `0x82` is the per-stage DPI value read
24
+ * and that it echoes its sub-command, confirmed the polling-rate byte at
25
+ * `0x81`, confirmed the packed byte-7 nibble reads for lift-off and motion
26
+ * sync agree with their symmetric `0x84` single-purpose reads, and added a
27
+ * button-binding codec. See
28
+ * `captures/incott-8k-wireless/write-roundtrip.hex` and
29
+ * `docs/incott-testing.md`.
30
+ *
31
+ * A FIFTH round, 2026-09-08, RELOCATED battery entirely. Charging a unit
32
+ * through a full cycle (roughly 60% to roughly 97%) while polling the
33
+ * `0x8e`/sub `0x01` feature-report reply showed byte 6 never move at all —
34
+ * the exact frame `09 8e 01 5a 04 84 38 01` the entire time. A constant is
35
+ * not a battery reading; see `INCOTT_CMD_QUERY_BATTERY` and
36
+ * `incottDecodeBattery` for what this disproves and why the codec is kept
37
+ * anyway (regression coverage), and `docs/incott-testing.md` for the write-up.
38
+ * The real level lives in an UNSOLICITED INPUT report the mouse emits on
39
+ * report id 0x09 while it is actively being used — not a feature-report
40
+ * reply to any request this driver sends. See `incottDecodeInputStatus` for
41
+ * the codec and `src/drivers/incott/hid.ts`'s `onInputReport` for how the
42
+ * WebHID client listens for it and caches the result.
43
+ *
44
+ * A FOURTH fix, same day, closed a second DPI bug found by an owner report:
45
+ * `IncottHidClient.setDpi` was reading the active stage and then writing the
46
+ * requested DPI *into* that stage, silently overwriting whatever value the
47
+ * stage held — repeated use progressively destroyed the mouse's factory
48
+ * table (one owner's stage 2 was found changed from 1600 to 800 this way).
49
+ * DPI is genuinely four independent operations, not one: select the active
50
+ * stage (`INCOTT_CMD_SET_DPI_STAGE`/`incottEncodeSetActiveDpiStage`, `09 03
51
+ * 06 <idx>`), edit a stage's value (`INCOTT_CMD_SET_DPI`/`incottEncodeSetDpi`,
52
+ * `09 02 <idx> <lo> <hi>`), read which stage is active
53
+ * (`INCOTT_CMD_QUERY_DPI_STAGE`, `09 83 06`), and read a stage's value
54
+ * (`INCOTT_CMD_QUERY_DPI_STAGE_VALUE`, `09 82 <idx>`). Select and edit were
55
+ * verified as genuinely distinct operations: selecting stages 0, 3, 5, then 1
56
+ * in turn each read back correctly via `0x83`/`0x06`, and reading all six
57
+ * stages via `0x82` before and after showed the table's contents completely
58
+ * unchanged by those selects. See `INCOTT_CMD_SET_DPI_STAGE` for the full
59
+ * writeup, `src/drivers/incott/hid.ts` for how the driver now exposes
60
+ * `setActiveDpiStage`/`setDpiStageValue` as OpenMouse's existing generic
61
+ * multi-stage DPI editor contract, and
62
+ * `captures/incott-8k-wireless/write-roundtrip.hex` /
63
+ * `docs/incott-testing.md` for the capture.
64
+ *
65
+ * All traffic is HID feature reports on report ID 0x09. Requests are 9 bytes
66
+ * `[0x09, cmd, sub, ...args]`; WebHID's `sendFeatureReport` takes the report
67
+ * ID as a separate argument, so the payloads this module builds are 8 bytes
68
+ * and omit it. Responses are read with `receiveFeatureReport(0x09)`, which
69
+ * returns the report ID at byte 0, so decoders index frames that include it.
70
+ *
71
+ * Opcodes are paired: `0x0N` sets a value, `0x8N` queries it. The device
72
+ * latches a single shared response buffer — see `incottFrameMatches` and
73
+ * `src/drivers/incott/hid.ts` for how the driver layer avoids decoding a
74
+ * frame left over from a previous query.
75
+ *
76
+ * A SIXTH round, 2026-09-10, instrumented Incott's own web configurator again,
77
+ * this time with every click LABELLED, settling the performance-mode
78
+ * value-to-label mapping left open by the 2026-09-07 capture: HP=2, Corded=1,
79
+ * LP=0 — the REVERSE of the vendor UI's own left-to-right display order. See
80
+ * `INCOTT_SUB_PERFORMANCE` for the labelled capture,
81
+ * `INCOTT_PERFORMANCE_MODE_TO_WIRE`/`incottPerformanceModeToWire` for the
82
+ * table it lives in, and `src/drivers/incott/hid.ts`'s `setPowerMode`/
83
+ * `getPowerModes` for where it is now wired into OpenMouse's shared
84
+ * `powerMode`/`powerModes` contract. The same session also verified the
85
+ * receiver LED labels (previously prior art, now confirmed — see
86
+ * `INCOTT_RECEIVER_LED_MODES`), found a DPI-write axis byte at payload index
87
+ * 7 (see `incottEncodeSetDpi`), and established that onboard profiles are a
88
+ * vendor-software construct with no on-device select command. See
89
+ * `docs/incott-testing.md` and
90
+ * `captures/incott-8k-wireless/vendor-tool-session-2026-09-10.hex`.
91
+ *
92
+ * This module must not import WebHID types or talk to a device; see
93
+ * `src/drivers/incott/hid.ts` for the WebHID client.
94
+ */
95
+ export declare const INCOTT_VENDOR_ID = 2362;
96
+ /** The 2.4 GHz dongle's product id — "incott 8K wireless mouse" in its product string. */
97
+ export declare const INCOTT_PRODUCT_ID = 21036;
98
+ /**
99
+ * The WIRED product id — hardware-verified 2026-09-08 by plugging the mouse
100
+ * in over USB and reading `device.productId` directly: it enumerates as
101
+ * `0x622C`, not `0x522C`. This used to be named `INCOTT_PRODUCT_ID_CHARGING`
102
+ * and `incottIsChargingProduct` treated it as a charging FLAG — that was the
103
+ * wrong axis. `0x622C` means the CONNECTION is wired; charging is a
104
+ * consequence of being plugged in, not the thing this id actually encodes.
105
+ * See `incottIsWiredProduct` (the renamed helper) and
106
+ * `IncottHidClient.readStatus`, which now derives both `connectionType` and
107
+ * `batteryState: "Charging"` from wired-ness rather than from a constant
108
+ * that claimed to mean "charging."
109
+ */
110
+ export declare const INCOTT_PRODUCT_ID_WIRED = 25132;
111
+ export declare const INCOTT_PRODUCT_IDS: readonly number[];
112
+ /** The vendor collection that answers protocol requests. */
113
+ export declare const INCOTT_USAGE_PAGE = 65285;
114
+ /** Any vendor-defined page, used as a fallback when 0xFF05 is absent. */
115
+ export declare const INCOTT_VENDOR_USAGE_PAGE_MIN = 65280;
116
+ export declare const INCOTT_REPORT_ID = 9;
117
+ /** Payload length excluding the report ID (WebHID sends it separately). */
118
+ export declare const INCOTT_PAYLOAD_LENGTH = 8;
119
+ /** Length requested from receiveFeatureReport, including the report ID. */
120
+ export declare const INCOTT_RESPONSE_LENGTH = 64;
121
+ /** Set opcodes. Query opcodes are the same value with bit 7 set. */
122
+ export declare const INCOTT_CMD_SET_POLLING = 1;
123
+ /**
124
+ * Writes the actual DPI value (see `incottEncodeSetDpi`), NOT a preset index.
125
+ * Proven on hardware 2026-09-07 against a real G23V2Pro; this used to be
126
+ * `0x03`, which was never verified and is not what the vendor tool sends.
127
+ */
128
+ export declare const INCOTT_CMD_SET_DPI = 2;
129
+ export declare const INCOTT_CMD_SET_SENSOR = 4;
130
+ export declare const INCOTT_CMD_SET_TIMING = 5;
131
+ /**
132
+ * Button binding write, `09 06 <button 0..5> <...payload>` — round-trip
133
+ * confirmed on hardware 2026-09-08: the vendor tool wrote
134
+ * `09 06 00 01 00 f0` to button 0, and reading it back via `0x86`/sub `00`
135
+ * afterwards returned the identical three payload bytes. See
136
+ * `incottEncodeSetButtonBinding` — this only encodes the raw binding; the
137
+ * meaning of its bytes (key code vs. macro vs. remap) is NOT established, so
138
+ * nothing here interprets them.
139
+ */
140
+ export declare const INCOTT_CMD_SET_BUTTON = 6;
141
+ /**
142
+ * Announces one 32-byte chunk of a macro buffer:
143
+ * `09 07 <chunks> <chunk index> <bytes per chunk> <buffer id>`.
144
+ *
145
+ * Each header is followed by the chunk itself as a 32-byte OUTPUT report on
146
+ * the same id — see `IncottHidClient.uploadMacro`.
147
+ */
148
+ export declare const INCOTT_CMD_MACRO_CHUNK = 7;
149
+ export declare const INCOTT_CMD_SET_RECEIVER_LED = 8;
150
+ /**
151
+ * Selects which of the six DPI stages is ACTIVE: `09 03 06 <idx>` (command
152
+ * `0x03`, sub-command `INCOTT_SUB_DPI_STAGE`, then the stage index). Pairs
153
+ * with `INCOTT_CMD_QUERY_DPI_STAGE` (`0x83`), which reads the active index
154
+ * back at the same sub-command — see `incottEncodeSetActiveDpiStage`.
155
+ *
156
+ * This is a SELECT, not an EDIT: it never touches the six-stage table's
157
+ * stored values. Verified on hardware 2026-09-08 — selecting stage 0, 3, 5,
158
+ * then 1 in turn each read back identically via `0x83`/`0x06`, and reading
159
+ * all six stages via `0x82` before and after showed the table completely
160
+ * unchanged by those selects.
161
+ *
162
+ * IMPORTANT MISLABEL TO NOT REPEAT: IncottHIDApp calls this command "set
163
+ * DPI" and treats its six "DPI presets" as if picking one changes the DPI
164
+ * value. It does not — it only changes which already-stored stage answers
165
+ * as active. The bug this driver used to have (`setDpi` writing the
166
+ * requested value into whichever stage happened to be active, silently
167
+ * overwriting the factory table one stage at a time) came directly from
168
+ * conflating this select with `INCOTT_CMD_SET_DPI` (`0x02`), the command
169
+ * that actually edits a stage's stored value. See `incottEncodeSetDpi` and
170
+ * `docs/incott-testing.md`.
171
+ */
172
+ export declare const INCOTT_CMD_SET_DPI_STAGE = 3;
173
+ /**
174
+ * Returns the active DPI *stage index* (0-5), not a DPI value — see
175
+ * `incottDecodeDpiStageIndex`. Still `0x83`; only the interpretation of its
176
+ * payload changed.
177
+ */
178
+ export declare const INCOTT_CMD_QUERY_DPI_STAGE = 131;
179
+ /**
180
+ * Reads the numeric DPI value stored in one of the six stages,
181
+ * `09 82 <stage 0..5>` -> little-endian uint16 at RESPONSE bytes 3-4 (same
182
+ * `wire = dpi/50 - 1` encoding as the write). Verified on hardware
183
+ * 2026-09-08 by reading all six stages back as 400/800/1600/2400/3200/6400
184
+ * (wire 0x07/0x0f/0x1f/0x2f/0x3f/0x7f), then writing 25000 to stage 2 and
185
+ * reading it back as exactly 25000, then restoring 1600 and reading that
186
+ * back too — six independent points on `dpi = (wire + 1) * 50`, plus a
187
+ * write/restore round-trip. This was previously `INCOTT_CMD_UNKNOWN_82`: an
188
+ * earlier opcode sweep only ever tried sub `0x00` and got back an
189
+ * uninterpreted payload (`09 82 00 07 00 …`) — the same "sub-commands are
190
+ * not optional" lesson `0x8e` (battery) taught. See `incottDecodeDpiStage`.
191
+ */
192
+ export declare const INCOTT_CMD_QUERY_DPI_STAGE_VALUE = 130;
193
+ export declare const INCOTT_CMD_QUERY_POLLING = 129;
194
+ export declare const INCOTT_CMD_QUERY_SENSOR = 132;
195
+ export declare const INCOTT_CMD_QUERY_TIMING = 133;
196
+ export declare const INCOTT_CMD_QUERY_RECEIVER_LED = 136;
197
+ /**
198
+ * Answers, but byte 8 of the reply returned the same constant `0x5a` (90) on
199
+ * every capture ever taken, across every device state and both capture
200
+ * sessions (2026-09-07 read-only sweep and the later vendor-tool traffic).
201
+ * That is disproof, not confirmation, that byte 8 is a battery percentage —
202
+ * see `docs/incott-testing.md`. Nothing in this driver decodes this response
203
+ * any more. DISPROVEN A SECOND TIME on 2026-09-08: `0x8e`/sub `0x01` byte 6
204
+ * (see below), the value this comment used to point to as "the real battery
205
+ * percentage," is ALSO a constant — see `INCOTT_CMD_QUERY_BATTERY`. The real
206
+ * battery level lives in an unsolicited input report; see
207
+ * `incottDecodeInputStatus`. Kept only because the opcode itself still
208
+ * answers and its real meaning is an open question worth recording.
209
+ */
210
+ export declare const INCOTT_CMD_QUERY_STATUS = 137;
211
+ export declare const INCOTT_CMD_QUERY_IDENTITY = 143;
212
+ /**
213
+ * Battery percentage, but ONLY on sub-command `0x01` — the original opcode
214
+ * sweep swept every command with sub `0x00` and concluded `0x8e` was
215
+ * unimplemented because it never answered. Sub-commands are not optional on
216
+ * this opcode (or on `0x86`, which the vendor tool queries as `09 86 09`).
217
+ *
218
+ * DISPROVEN 2026-09-08, the same way `0x89` byte 8 was disproven before it
219
+ * (see `INCOTT_CMD_QUERY_STATUS`): charging a unit through a full cycle from
220
+ * roughly 60% to roughly 97% while polling this response showed byte 6 NEVER
221
+ * CHANGE — the identical frame `09 8e 01 5a 04 84 38 01` the entire time,
222
+ * `0x38` = 56 throughout. A value that does not move while the real battery
223
+ * level visibly does cannot be a battery reading; it is a constant of unknown
224
+ * meaning, exactly like `0x89` byte 8 before it. `incottDecodeBattery` is
225
+ * kept only as a codec (its mechanical byte-6 decode is unchanged and still
226
+ * tested) and for the driver-level regression test that battery is no longer
227
+ * sourced from here — see `IncottHidClient.readStatus` and
228
+ * `docs/incott-testing.md`. The real battery percentage is a field of the
229
+ * unsolicited input report the mouse emits while in use — see
230
+ * `incottDecodeInputStatus`.
231
+ */
232
+ export declare const INCOTT_CMD_QUERY_BATTERY = 142;
233
+ export declare const INCOTT_SUB_BATTERY = 1;
234
+ /**
235
+ * The report id the mouse's UNSOLICITED input reports arrive on — the same
236
+ * value as `INCOTT_REPORT_ID` (`0x09`), which this module otherwise uses only
237
+ * for feature-report request/response pairs. These input reports are NOT a
238
+ * reply to anything this driver sends: the device emits them on its own,
239
+ * only while it is actively being used (moved or clicked), carrying battery
240
+ * and a packed DPI-stage/polling-rate snapshot. See `incottDecodeInputStatus`
241
+ * and `src/drivers/incott/hid.ts`'s `onInputReport`.
242
+ */
243
+ export declare const INCOTT_INPUT_REPORT_ID = 9;
244
+ /**
245
+ * Button binding read, `09 86 <button 0..5>` -> response bytes 3-5 = the raw
246
+ * three-byte binding written by `INCOTT_CMD_SET_BUTTON` at the same index.
247
+ * Round-trip confirmed on hardware 2026-09-08 (see `INCOTT_CMD_SET_BUTTON`).
248
+ * The device has six buttons; reading indices 0-5 on the unit under test
249
+ * returned:
250
+ * 0 -> 01 00 f0 3 -> 01 00 f3
251
+ * 1 -> 01 00 f1 4 -> 01 00 f4
252
+ * 2 -> 01 00 f2 5 -> 07 00 03
253
+ * (left, right, middle, forward, back, DPI — physically, in some order).
254
+ * This was previously `INCOTT_CMD_UNKNOWN_86`. Sub-command `0x09` on the
255
+ * same command reads the onboard profile index instead — see
256
+ * `INCOTT_SUB_PROFILE_INDEX`. The binding itself is a 32-bit little-endian
257
+ * action word; see `incottDecodeButtonBinding`.
258
+ */
259
+ export declare const INCOTT_CMD_QUERY_BUTTON = 134;
260
+ /** Button count: left, right, middle, forward, back, DPI. */
261
+ export declare const INCOTT_BUTTON_COUNT = 6;
262
+ /**
263
+ * Reads the onboard profile INDEX, `09 86 09` — not a button index, since
264
+ * buttons only go up to 5. Counterpart of the `09 06 09 <index>` write.
265
+ *
266
+ * Neither is implemented, and that is a finding rather than an omission: the
267
+ * index is real and sticks (0-3), but it gates nothing. Writing a setting
268
+ * while on one slot changes what every other slot reports, so there is a
269
+ * single settings store and the vendor replays every setting on a switch
270
+ * because the mouse holds none of them. Publishing OpenMouse's
271
+ * `profileCount`/`setProfile` contract — which describes ONBOARD profiles —
272
+ * would hand the user a selector that appears to work and does not. See
273
+ * `captures/incott-8k-wireless/profile-index-2026-09-11.hex`.
274
+ */
275
+ export declare const INCOTT_SUB_PROFILE_INDEX = 9;
276
+ /**
277
+ * Physical buttons, in left-to-right display order.
278
+ */
279
+ export declare const INCOTT_BUTTON_NAMES: readonly ["Left", "Right", "Middle", "Forward", "Back", "DPI"];
280
+ export type IncottButtonName = (typeof INCOTT_BUTTON_NAMES)[number];
281
+ /**
282
+ * Display order -> WIRE index. **These are not the same**, and assuming they
283
+ * were would silently swap two buttons.
284
+ *
285
+ * The vendor's per-model key table carries an explicit `matrix` field and
286
+ * addresses the device with it (`setMsK(dvar.key[i].matrix, code)`), not with
287
+ * the array position. For this family Forward sits at array index 3 with
288
+ * `matrix = 4`, and Back at array index 4 with `matrix = 3` — the two are
289
+ * transposed. Every other button's matrix equals its position.
290
+ */
291
+ export declare const INCOTT_BUTTON_WIRE_INDEX: Readonly<Record<IncottButtonName, number>>;
292
+ /**
293
+ * A keyboard action word, from the vendor's `kf_hw()` keyboard branch:
294
+ *
295
+ * no modifier: (keycode & 255) << 8 | 128
296
+ * with modifier: (keycode & 255) << 16 | (modifiers & 255) << 8
297
+ *
298
+ * The two forms are genuinely different shapes, not one with a zero
299
+ * modifier — an unmodified key sets the `0x80` marker in the low byte and
300
+ * puts the keycode one byte lower than a chord does.
301
+ */
302
+ export declare function incottKeyboardActionCode(keycode: number, modifiers?: number): number;
303
+ /**
304
+ * Everything a button can be set to, in display order: the mouse, DPI and
305
+ * media actions above, then individual keys, then common chords.
306
+ *
307
+ * Keyboard bindings are enumerated rather than left out. The encoding is
308
+ * parametric (any of 256 keycodes against any of 256 modifier masks) and the
309
+ * shared `buttonOptions` contract is a flat list of labels, so the full space
310
+ * cannot be offered — but a curated list covers what people actually bind,
311
+ * and it is the same approach the MCHOSE driver in this repo already takes.
312
+ */
313
+ export declare const INCOTT_BUTTON_ACTIONS: ReadonlyArray<readonly [string, number]>;
314
+ /** Macro loop modes, in wire order. */
315
+ export declare const INCOTT_MACRO_LOOP_MODES: readonly ["untilKeyRelease", "untilAnyKey", "cycle"];
316
+ export type IncottMacroLoop = (typeof INCOTT_MACRO_LOOP_MODES)[number];
317
+ /** One key event in a macro: a press or a release, then a delay. */
318
+ export interface IncottMacroStep {
319
+ /** HID keyboard usage code. */
320
+ key: number;
321
+ /** True for a key-down event, false for key-up. */
322
+ press: boolean;
323
+ /** Delay after this event, milliseconds, 16-bit. */
324
+ delayMs: number;
325
+ }
326
+ export interface IncottMacro {
327
+ /** Which of the ten on-device macro buffers this occupies, 0-9. */
328
+ bufferId: number;
329
+ loop: IncottMacroLoop;
330
+ /** Repeat count, used by the `cycle` loop mode. */
331
+ cycles: number;
332
+ steps: readonly IncottMacroStep[];
333
+ /** The vendor's own identifier for the macro; echoed back in the buffer. */
334
+ uid: number;
335
+ }
336
+ /** A macro buffer is always this long, in ten 32-byte chunks. */
337
+ export declare const INCOTT_MACRO_BUFFER_BYTES = 320;
338
+ export declare const INCOTT_MACRO_CHUNK_BYTES = 32;
339
+ export declare const INCOTT_MACRO_CHUNK_COUNT: number;
340
+ export declare const INCOTT_MACRO_BUFFER_COUNT = 10;
341
+ /** Steps occupy bytes 4..287 at four bytes each, so 71 fit. */
342
+ export declare const INCOTT_MACRO_MAX_STEPS = 71;
343
+ /**
344
+ * Builds the 320-byte macro buffer, transcribed from the vendor bundle's
345
+ * `juji_to_hw()`.
346
+ *
347
+ * [0] buffer id
348
+ * [1] loop mode (0 until key release, 1 until any key, 2 cycle)
349
+ * [2..3] cycle count, LE16
350
+ * [4+4n] event flags: bit 0 always set, bit 7 set for a RELEASE
351
+ * [5+4n] HID keyboard usage code
352
+ * [6..7+4n] delay after the event, LE16 milliseconds
353
+ * [288..293] the ASCII name "Macro" followed by '1' + buffer id
354
+ * [304..307] (steps + 1) * 4 + 128, LE32
355
+ * [308..311] 16, 0, 232, 232 — constant in every buffer the vendor builds
356
+ * [312..315] uid, LE32
357
+ * [316..317] steps * 2, LE16
358
+ * [318] step count
359
+ *
360
+ * The buffer goes out as ten 32-byte chunks, each announced by
361
+ * `incottEncodeMacroChunkHeader` and then carried by a 32-byte OUTPUT report
362
+ * on the same report id — the only place this protocol uses an output report
363
+ * at all. That transport is not recoverable from the vendor bundle (the call
364
+ * carrying each chunk is defined in none of the files its page loads, and the
365
+ * HID method names resolve through variables at runtime), so it was captured
366
+ * from the running tool instead: see
367
+ * `captures/incott-8k-wireless/macro-upload-2026-09-11.hex`, and
368
+ * `IncottHidClient.uploadMacro` for the sender.
369
+ *
370
+ * Pinned byte-for-byte to that capture. There is no macro READ command, so
371
+ * nothing here can be verified against the device after the fact.
372
+ */
373
+ export declare function incottEncodeMacroBuffer(macro: IncottMacro): Uint8Array;
374
+ /**
375
+ * The 8-byte header announcing one chunk of a macro buffer:
376
+ * `09 07 0a <chunk index> 20 <buffer id>`.
377
+ *
378
+ * See `incottEncodeMacroBuffer` for why nothing sends this yet. Note the
379
+ * vendor slices its own payload as `mda.slice(i * 32, i * 64)`, which yields
380
+ * an EMPTY chunk for `i = 0` and over-long ones after — visibly a bug in its
381
+ * own uploader, and not reproduced here.
382
+ */
383
+ export declare function incottEncodeMacroChunkHeader(chunkIndex: number, bufferId: number): Uint8Array;
384
+ /** Splits a macro buffer into the ten chunks the upload sends. */
385
+ export declare function incottMacroChunks(buffer: Uint8Array): Uint8Array[];
386
+ /**
387
+ * Label for a 32-bit action word, or null when it is not one this driver
388
+ * knows.
389
+ *
390
+ * Macro bindings are named rather than listed: the vendor encodes them as
391
+ * `slot << 16 | 9` (confirmed 2026-09-11, where binding a button to macro
392
+ * slot 3 wrote `0x00030009`), so a label can be derived for any slot without
393
+ * putting ten entries in the picker. `incottButtonActionCode` deliberately
394
+ * does NOT reverse these — nothing can assign a macro until there is a UI to
395
+ * author one — so a macro binding reads back correctly and is left alone.
396
+ */
397
+ export declare function incottButtonActionLabel(code: number): string | null;
398
+ /** Low half of a macro button binding: `slot << 16 | 9`. */
399
+ export declare const INCOTT_BUTTON_MACRO_MARKER = 9;
400
+ /** 32-bit action word for a label, or null when the label is not in the table. */
401
+ export declare function incottButtonActionCode(label: string): number | null;
402
+ /**
403
+ * How many DPI stages the cycle uses by default — and the value this driver
404
+ * spent two sessions mistaking for a sub-command.
405
+ *
406
+ * `0x83`'s reply byte 2 is the stage COUNT, not an echo. Proven by the
407
+ * captures: the vendor sends `09 83 00` and gets `09 83 06 01` back, and a
408
+ * bare `09 83` sweep with no sub-command gets the same `06` — a byte the
409
+ * request never contained cannot be an echo. Byte 3 is the active index,
410
+ * which varies (`00`/`01`/`03`/`05`) while byte 2 stays `06`.
411
+ *
412
+ * This matters twice over:
413
+ * - `0x83` must NOT be treated as sub-echoing when matching responses. It
414
+ * belongs with `0x81`/`0x88`/`0x89`/`0x8f`, where byte 2 is data.
415
+ * - the `0x03` write carries the count alongside the index
416
+ * (`09 03 <count> <stage>`), so writing a hardcoded `06` while selecting
417
+ * a stage would reset a four-stage cycle back to six — the same shape of
418
+ * bug as the old `INCOTT_SUB_SET_DPI` constant below.
419
+ */
420
+ export declare const INCOTT_DPI_STAGE_COUNT_DEFAULT = 6;
421
+ /**
422
+ * Number of DPI stages the table holds. Both the `0x02` write and the `0x82`
423
+ * read take a stage index in this range as their second payload byte — see
424
+ * `incottEncodeSetDpi` and `incottDecodeDpiStage`.
425
+ *
426
+ * THIS WAS WRONG until 2026-09-08: the driver used to hardcode that byte as a
427
+ * constant `INCOTT_SUB_SET_DPI = 0x01`, which could only ever write stage 1
428
+ * of the table. Reading stages 0-5 on real hardware returned six independent
429
+ * points on the DPI line (wire 0x07/0x0f/0x1f/0x2f/0x3f/0x7f ->
430
+ * 400/800/1600/2400/3200/6400), proving the byte is a stage index, not a
431
+ * fixed sub-command.
432
+ */
433
+ export declare const INCOTT_DPI_STAGE_COUNT = 6;
434
+ export declare const INCOTT_SUB_LOD = 1;
435
+ export declare const INCOTT_SUB_RIPPLE = 2;
436
+ export declare const INCOTT_SUB_ANGLE_SNAP = 3;
437
+ export declare const INCOTT_SUB_MOTION_SYNC = 4;
438
+ /**
439
+ * Sub-command for the "Performance mode" sensor setting (labelled HP / Corded
440
+ * / LP in the vendor tool, described as trading performance for battery
441
+ * life). The value-to-label mapping is now CONFIRMED: captured 2026-09-10 by
442
+ * instrumenting Incott's own WebHID configurator with each click labelled
443
+ * (unlike the 2026-09-07 capture, which only recorded the raw writes):
444
+ *
445
+ * clicked "HP" -> TX 09 04 05 02
446
+ * clicked "Corded" -> TX 09 04 05 01
447
+ * clicked "LP" -> TX 09 04 05 00
448
+ *
449
+ * i.e. HP=2, Corded=1, LP=0. **This is the REVERSE of the vendor UI's
450
+ * left-to-right display order (HP | Corded | LP)** — exactly why this was
451
+ * captured with each click labelled rather than assumed from the on-screen
452
+ * order. See `INCOTT_PERFORMANCE_MODE_TO_WIRE`/`INCOTT_PERFORMANCE_MODE_FROM_WIRE`
453
+ * for the single named table this reversal lives in, and
454
+ * `incottEncodeSetPerformanceMode`.
455
+ */
456
+ export declare const INCOTT_SUB_PERFORMANCE = 5;
457
+ export declare const INCOTT_SUB_DEBOUNCE = 1;
458
+ /**
459
+ * Fire Key (rapid-fire) parameters, `09 05 02 <times> <interval ms>`.
460
+ *
461
+ * The last unidentified command in this protocol, settled 2026-09-11. The
462
+ * vendor calls it `setFKeyPm(lp, ir)` and only ever calls it for a button
463
+ * bound to `favFIRE`, deriving both values from that button's `itemdata` and
464
+ * clamping them to 3 and 255 respectively. Its own UI names the two fields:
465
+ * "Fire Key" / "Keep left-clicking according to the interval and times".
466
+ *
467
+ * Read back at `0x85`/`0x02`. On this hardware: `09 85 02 03 0a` — three
468
+ * clicks, 10 ms apart.
469
+ */
470
+ export declare const INCOTT_SUB_FIRE_KEY = 2;
471
+ /**
472
+ * Clicks per press, 1-3 — the ceiling the vendor clamps to.
473
+ *
474
+ * `INCOTT_FIRE_KEY_TIMES_HOLD` (0) is a real fourth setting, not an absence
475
+ * of one: it switches the button from a fixed burst to firing continuously
476
+ * while held. Confirmed against the vendor software 2026-09-11 by the device
477
+ * owner, which is the only way it could have been established — the value is
478
+ * in range for the write either way, so a round-trip proves nothing about
479
+ * what it MEANS.
480
+ */
481
+ export declare const INCOTT_FIRE_KEY_MAX_TIMES = 3;
482
+ /**
483
+ * Fire key "times" value that means hold-to-fire: the button keeps clicking
484
+ * at the configured interval for as long as it is held, and stops on
485
+ * release. See `INCOTT_FIRE_KEY_MAX_TIMES`.
486
+ */
487
+ export declare const INCOTT_FIRE_KEY_TIMES_HOLD = 0;
488
+ /** Milliseconds between clicks in a burst, one byte. */
489
+ export declare const INCOTT_FIRE_KEY_MAX_INTERVAL_MS = 255;
490
+ export declare const INCOTT_SUB_SLEEP = 3;
491
+ export declare const INCOTT_SUB_NONE = 0;
492
+ /**
493
+ * DPI lives in a six-stage table, each stage a linear value — not an index
494
+ * into a preset table. The wire value is little-endian at payload bytes 2-3
495
+ * (write) / response bytes 3-4 (read):
496
+ * wire = dpi / 50 - 1 dpi = (wire + 1) * 50
497
+ *
498
+ * Verified on hardware 2026-09-08 by reading all six stages back as
499
+ * 400/800/1600/2400/3200/6400 (wire 0x07/0x0f/0x1f/0x2f/0x3f/0x7f) — six
500
+ * independent points on this line — then writing 25000 to stage 2 (wire 499)
501
+ * and reading back exactly 25000, then restoring 1600 and reading that back
502
+ * too. (An earlier, narrower proof from 2026-09-07 against a G23V2Pro only
503
+ * ever exercised stage 1: `TX 09 02 01 0f 00` -> 800 DPI, `TX 09 02 01 f3 01`
504
+ * -> 25000 DPI.) See `incottEncodeSetDpi` and `incottDecodeDpiStage`.
505
+ *
506
+ * The vendor's own device definition (js/gvarG23-v102.js) pairs two PixArt
507
+ * sensor variants with different ceilings, both counting up from 50 in steps
508
+ * of 50:
509
+ * sensor 0x3395 (PAW3395): 32000
510
+ * sensor 0x3950 (PAW3950): 45000
511
+ * The fitted sensor IS readable — the identity reply carries it (see
512
+ * `incottDecodeIdentity`) — so `readStatus` narrows the ceiling it OFFERS to
513
+ * whichever sensor answered, via `incottDpiMaxForSensor`. This constant stays
514
+ * the higher of the two: it is the bound on what the protocol can express,
515
+ * and the encoder must keep accepting a value the app is entitled to send.
516
+ * That mirrors the polling rate, where `supportedPollingRates` narrows by
517
+ * connection while `incottEncodeSetPollingRate` still accepts the full
518
+ * ladder.
519
+ */
520
+ export declare const INCOTT_DPI_MIN = 50;
521
+ export declare const INCOTT_DPI_MAX = 45000;
522
+ /** The PAW3395's ceiling in the vendor's own DPI table. */
523
+ export declare const INCOTT_DPI_MAX_PAW3395 = 32000;
524
+ /**
525
+ * The DPI ceiling to OFFER for a fitted sensor, matching the table the vendor
526
+ * builds in `getStDPI`.
527
+ *
528
+ * Worth being precise about what this is and is not. It is the vendor's UI
529
+ * limit, not a proven firmware limit: this contributor's PAW3950 accepted
530
+ * 45000 over the cable even though the connection-indexed sensor byte read
531
+ * PAW3395 there (see `captures/incott-8k-wireless/wired-dpi-ceiling-2026-09-11.hex`),
532
+ * so a real PAW3395 unit has never been tested and may well accept more. It
533
+ * is used because offering exactly what the vendor offers cannot surprise
534
+ * anyone, and because the alternative — advertising 45000 to a Ghero — risks
535
+ * a silent refusal on a model nobody here can test.
536
+ */
537
+ export declare function incottDpiMaxForSensor(sensorId: number | null): number;
538
+ export declare const INCOTT_DPI_STEP = 50;
539
+ /**
540
+ * NOT the writable DPI range (see `INCOTT_DPI_MIN`/`INCOTT_DPI_MAX` above for
541
+ * that) — the vendor's device definition calls this list the six DEFAULT
542
+ * STAGE PRESETS. `0x83`/`0x06` reports which of these six stages is active as
543
+ * an index 0-5 (see `incottDecodeDpiStageIndex`), not a DPI value. Kept as a
544
+ * convenience list of round numbers; do not use it to validate or decode a
545
+ * DPI write.
546
+ */
547
+ export declare const INCOTT_DPI_DEFAULT_STAGE_PRESETS: readonly number[];
548
+ /**
549
+ * The full polling-rate ladder, available only over the 2.4 GHz wireless
550
+ * connection (`INCOTT_PRODUCT_ID`, `0x522C`). See
551
+ * `INCOTT_POLLING_STEPS_HZ_WIRED` for the lower ceiling the owner confirmed
552
+ * on hardware when the mouse is plugged in.
553
+ */
554
+ export declare const INCOTT_POLLING_STEPS_HZ: readonly number[];
555
+ /**
556
+ * Wired ceiling — HARDWARE-VERIFIED: the owner confirmed the mouse only
557
+ * reaches 1000 Hz over the USB cable (`INCOTT_PRODUCT_ID_WIRED`, `0x622C`);
558
+ * 2000/4000/8000 Hz are wireless-only. Offering one of those over the cable
559
+ * would produce a write the device silently refuses, which
560
+ * `IncottHidClient.setPollingRate`'s read-back verification would then
561
+ * report as a failure on every attempt — so `readStatus()` publishes this
562
+ * narrower list instead of the full one whenever `incottIsWiredProduct` is
563
+ * true. See `docs/incott-testing.md`.
564
+ */
565
+ export declare const INCOTT_POLLING_STEPS_HZ_WIRED: readonly number[];
566
+ export declare const INCOTT_POLLING_WIRE_TO_HZ: Readonly<Record<number, number>>;
567
+ export declare const INCOTT_POLLING_HZ_TO_WIRE: Readonly<Record<number, number>>;
568
+ /**
569
+ * Lift-off distance is carried in tenths of a millimetre.
570
+ *
571
+ * VERIFIED ON HARDWARE 2026-09-08. Setting 0.7 mm in Incott's own web
572
+ * configurator and then reading `0x84`/sub `0x01` returned byte 3 = `2`,
573
+ * so hardware 2 = 0.7 mm. That confirms IncottHIDApp's mapping, which is
574
+ * what `INCOTT_LOD_WIRE_TO_TENTHS` below encodes.
575
+ *
576
+ * It also disproves a reading of the vendor's own device definition
577
+ * (js/gvarG23-v102.js), which pairs `lodUI = [0.7, 1, 2]` with
578
+ * `lodHW = [0, 1, 2]`. Those two arrays are NOT index-aligned — taking
579
+ * them as a pair implies hardware 0 = 0.7 mm, which the device
580
+ * contradicts. Do not 'fix' this mapping from that file.
581
+ *
582
+ * Remaining nuance: only the 0.7 mm point was read directly. Hardware 0
583
+ * and 1 are 1 mm and 2 mm in that order per IncottHIDApp; since the
584
+ * mapping is a bijection over {0,1,2} and its 0.7 mm claim proved correct,
585
+ * the other two follow, but neither has been read back individually.
586
+ */
587
+ export declare const INCOTT_LOD_STEPS_TENTHS: readonly number[];
588
+ export declare const INCOTT_LOD_WIRE_TO_TENTHS: Readonly<Record<number, number>>;
589
+ export declare const INCOTT_LOD_TENTHS_TO_WIRE: Readonly<Record<number, number>>;
590
+ export declare const INCOTT_DEBOUNCE_MIN_MS = 0;
591
+ export declare const INCOTT_DEBOUNCE_MAX_MS = 30;
592
+ export declare const INCOTT_SLEEP_MIN_S = 1;
593
+ export declare const INCOTT_SLEEP_MAX_S = 900;
594
+ /** All three raw wire values (LP/Corded/HP) are now hardware-confirmed — see `INCOTT_SUB_PERFORMANCE`. */
595
+ export declare const INCOTT_PERFORMANCE_MODE_MIN = 0;
596
+ export declare const INCOTT_PERFORMANCE_MODE_MAX = 2;
597
+ /**
598
+ * The single named table the HP/Corded/LP value-to-label reversal lives in —
599
+ * see `INCOTT_SUB_PERFORMANCE` for the capture that confirmed it. Keys are the
600
+ * vendor tool's own display labels; `INCOTT_PERFORMANCE_MODE_NAMES` lists them
601
+ * in the vendor UI's own left-to-right order (HP, Corded, LP) for advertising
602
+ * to the app, while this table (and its inverse,
603
+ * `INCOTT_PERFORMANCE_MODE_FROM_WIRE`) hold the REVERSED wire values.
604
+ * `incottPerformanceModeToWire`/`incottPerformanceModeFromWire` are the
605
+ * intended entry points; the raw tables are exported for tests.
606
+ */
607
+ export declare const INCOTT_PERFORMANCE_MODE_NAMES: readonly string[];
608
+ /** name -> raw wire value. See `INCOTT_PERFORMANCE_MODE_NAMES`'s doc comment for the reversal warning. */
609
+ export declare const INCOTT_PERFORMANCE_MODE_TO_WIRE: Readonly<Record<string, number>>;
610
+ /** raw wire value -> name. The inverse of `INCOTT_PERFORMANCE_MODE_TO_WIRE`. */
611
+ export declare const INCOTT_PERFORMANCE_MODE_FROM_WIRE: Readonly<Record<number, string>>;
612
+ /** Validated name -> wire lookup for `incottEncodeSetPerformanceMode`/`IncottHidClient.setPowerMode`. Returns `null` for an unknown name rather than throwing, so callers can reject before writing anything. */
613
+ export declare function incottPerformanceModeToWire(name: string): number | null;
614
+ /** Wire -> validated name lookup, the inverse of `incottPerformanceModeToWire`. Returns `null` for a value outside 0-2. */
615
+ export declare function incottPerformanceModeFromWire(wire: number): string | null;
616
+ /**
617
+ * A curated subset of the verified 1-900s sleep-timer range to offer in the
618
+ * app's dropdown, in the same style as GEARHUB_SLEEP_OPTIONS and
619
+ * MCHOSE_SLEEP_OPTIONS: the firmware accepts any integer second count in
620
+ * range (see `incottEncodeSetSleep`), this is just a sane list of presets.
621
+ * 900s (15 minutes) is the documented maximum.
622
+ */
623
+ export declare const INCOTT_SLEEP_OPTIONS: readonly number[];
624
+ export declare const INCOTT_RECEIVER_LED_MODES: readonly string[];
625
+ export type IncottToggleKind = "motionSync" | "angleSnapping" | "rippleControl";
626
+ export declare const INCOTT_TOGGLE_SUB: Readonly<Record<IncottToggleKind, number>>;
627
+ /**
628
+ * Throws `RangeError` unless `dpi` is a value the six-stage table can hold.
629
+ * Split out from `incottEncodeSetDpi` so `IncottHidClient.setDpi` can reject
630
+ * an invalid value before touching the device — determining which stage is
631
+ * active requires a query, and an obviously-invalid DPI should never cost a
632
+ * round-trip.
633
+ */
634
+ export declare function incottValidateDpi(dpi: number): void;
635
+ /**
636
+ * EDITS the DPI value stored in one stage — distinct from
637
+ * `incottEncodeSetActiveDpiStage`, which only SELECTS which stage is active
638
+ * and never touches a stored value. `stage` is a table index 0-5, NOT a
639
+ * sub-command — see `INCOTT_DPI_STAGE_COUNT` for the hardware proof that this
640
+ * byte varies (the driver used to hardcode it as a constant `0x01`, which
641
+ * could only ever reach stage 1). The value itself is a plain little-endian
642
+ * uint16 "wire" value — see the comment on `INCOTT_DPI_MIN` for the
643
+ * conversion and the captured proof.
644
+ *
645
+ * PAYLOAD INDEX 7 IS AN AXIS BYTE, discovered 2026-09-10: the full write is
646
+ * `02 <stage> <lo> <hi> 00 00 00 <axis>`, where `axis` 0 = both axes, 1 = X
647
+ * only, 2 = Y only. This encoder always emits trailing zeros (see `payload`),
648
+ * and the `axis` argument selects it. Independent X/Y IS implemented and
649
+ * hardware-verified — the matching per-axis read is `incottEncodeQueryDpiAxis`,
650
+ * which an earlier probe concluded did not exist because X and Y happened to
651
+ * be equal at the time.
652
+ */
653
+ /**
654
+ * Which axis a DPI write targets, and which one a read asks for.
655
+ *
656
+ * On the WRITE the value rides at payload byte 7; on the READ it is request
657
+ * byte 2 and the reply echoes it back at byte 8. Hardware-verified
658
+ * 2026-09-11: writing X=800/Y=1600, X=2400/Y=400 and X=1000/Y=1000 to one
659
+ * stage read back exactly, each axis independently.
660
+ *
661
+ * `both` is what a plain `incottEncodeSetDpi` sends, and what reading with no
662
+ * axis byte returns.
663
+ */
664
+ export declare const INCOTT_DPI_AXIS: {
665
+ readonly both: 0;
666
+ readonly x: 1;
667
+ readonly y: 2;
668
+ };
669
+ export type IncottDpiAxis = keyof typeof INCOTT_DPI_AXIS;
670
+ export declare function incottEncodeSetDpi(stage: number, dpi: number, axis?: IncottDpiAxis): Uint8Array;
671
+ /**
672
+ * `09 82 <stage> <axis>` — reads one axis of one stage.
673
+ *
674
+ * WHY THIS EXISTS, given a plain `09 82 <stage>` already reads a value: this
675
+ * driver previously recorded that no per-axis read existed, on the strength
676
+ * of a probe where all three axis values came back identical. They were
677
+ * identical because X and Y were BOTH at the factory 1600 at the time — the
678
+ * probe could not tell "no per-axis read" from "per-axis read whose axes
679
+ * happen to match". Confirmed 2026-09-11 by setting them apart first.
680
+ */
681
+ export declare function incottEncodeQueryDpiAxis(stage: number, axis: IncottDpiAxis): Uint8Array;
682
+ /**
683
+ * Writes the DPI cycle: `09 03 <count> <stage>` — how many stages the cycle
684
+ * uses, and which one is active. Does NOT write a DPI value and does NOT
685
+ * alter any stage's stored value; see `INCOTT_CMD_SET_DPI_STAGE` for the
686
+ * hardware proof (select 0/3/5/1, table unchanged) and for why this is a
687
+ * distinct operation from `incottEncodeSetDpi`, which edits a stage's stored
688
+ * value.
689
+ *
690
+ * `count` IS REQUIRED, and callers must pass what the device currently
691
+ * reports rather than a constant — the byte used to be hardcoded `0x06` in
692
+ * the belief that it was a sub-command, which would silently reset a
693
+ * four-stage cycle to six every time a stage was selected. See
694
+ * `INCOTT_DPI_STAGE_COUNT_DEFAULT`.
695
+ */
696
+ export declare function incottEncodeSetDpiCycle(count: number, stage: number): Uint8Array;
697
+ export declare function incottEncodeSetPollingRate(hz: number): Uint8Array;
698
+ export declare function incottEncodeSetLiftOff(tenthsMm: number): Uint8Array;
699
+ export declare function incottEncodeSetToggle(kind: IncottToggleKind, on: boolean): Uint8Array;
700
+ /**
701
+ * Encodes a button binding write, `09 06 <button 0..5> <32-bit action, LE>`.
702
+ *
703
+ * The action is a 32-bit little-endian word — see `INCOTT_BUTTON_ACTIONS`
704
+ * for the labelled codes. Confirmed against hardware: this unit's factory
705
+ * binding for the DPI button reads back `07 00 03`, and the vendor's own
706
+ * encoder returns `0x00030007` for that function, which is the same word.
707
+ *
708
+ * `button` is the WIRE index, which is not the physical left-to-right order
709
+ * — see `INCOTT_BUTTON_WIRE_INDEX`.
710
+ */
711
+ export declare function incottEncodeSetButtonBinding(button: number, code: number): Uint8Array;
712
+ /**
713
+ * Encodes the raw 0-2 performance-mode value. The value-to-label mapping
714
+ * (HP=2 / Corded=1 / LP=0) is now CONFIRMED — see `INCOTT_SUB_PERFORMANCE`
715
+ * for the labelled capture and its REVERSED-vs-UI warning. Most callers
716
+ * should go through `incottPerformanceModeToWire`/`IncottHidClient.setPowerMode`
717
+ * with a name instead of a raw value; this function is the low-level codec
718
+ * both build on.
719
+ */
720
+ export declare function incottEncodeSetPerformanceMode(mode: number): Uint8Array;
721
+ export declare function incottEncodeSetDebounce(ms: number): Uint8Array;
722
+ export declare function incottEncodeSetSleep(seconds: number): Uint8Array;
723
+ export declare function incottEncodeSetReceiverLed(mode: number): Uint8Array;
724
+ export declare function incottEncodeQuery(cmd: number, sub?: number): Uint8Array;
725
+ /**
726
+ * The models that share `093A:522C`/`093A:622C`. All six enumerate under the
727
+ * same two product ids, so the USB descriptor cannot tell them apart — the
728
+ * model is carried in the identity reply instead (`incottDecodeIdentity`).
729
+ *
730
+ * "Zero 29"/"Zero 39" are the English series names the vendor's own
731
+ * `text_en` bundle uses (`msg94`/`msg95`); its code calls the same two models
732
+ * `G29` and `FM23` internally and renders them as 零29/零39.
733
+ */
734
+ export type IncottModel = "Ghero" | "G23" | "G24" | "G23V2" | "Zero 29" | "Zero 39";
735
+ /** PixArt PAW3395 — capped at 32000 DPI in the vendor's own DPI table. */
736
+ export declare const INCOTT_SENSOR_PAW3395 = 13205;
737
+ /** PixArt PAW3950 — capped at 45000 DPI, and what the "Pro" suffix means. */
738
+ export declare const INCOTT_SENSOR_PAW3950 = 14672;
739
+ export interface IncottDeviceIdentity {
740
+ /** Space-separated hex of the identity payload, for the details panel. */
741
+ raw: string;
742
+ /** Decoded model, or null when byte 3 carries a code this table does not know. */
743
+ model: IncottModel | null;
744
+ /** Raw byte 3, kept even when unrecognised so an unknown model can still be reported. */
745
+ modelCode: number | null;
746
+ /** Model plus a " Pro" suffix when the PAW3950 is fitted, e.g. "G23V2 Pro". */
747
+ displayName: string | null;
748
+ /** The FITTED sensor: `INCOTT_SENSOR_PAW3395` or `INCOTT_SENSOR_PAW3950`. */
749
+ sensorId: number | null;
750
+ /** True when the PAW3950 is fitted — what the vendor's "Pro" suffix means. */
751
+ isPro: boolean;
752
+ /** True when byte 4 reports the 8 KHz receiver. */
753
+ is8KReceiver: boolean;
754
+ }
755
+ /**
756
+ * A response frame is trustworthy only when the report ID, the command echo
757
+ * and (when one was sent) the sub-command echo all agree with the request.
758
+ * The device latches a single shared response buffer, so a frame left over
759
+ * from an earlier query will otherwise be decoded as a real value.
760
+ */
761
+ export declare function incottFrameMatches(frame: Uint8Array, cmd: number, sub: number | null, axis?: number | null): boolean;
762
+ /** The DPI cycle as the device reports it: how many stages, and which is live. */
763
+ export interface IncottDpiCycle {
764
+ /** Stages in the cycle, 1..`INCOTT_DPI_STAGE_COUNT`. */
765
+ count: number;
766
+ /** Active stage, 0-based and always below `count`. */
767
+ active: number;
768
+ }
769
+ /**
770
+ * `09 83` -> `<count> <active>` at response bytes 2 and 3.
771
+ *
772
+ * Byte 3 was proven not to be a DPI-value index on hardware 2026-09-07:
773
+ * decoding it through `INCOTT_DPI_DEFAULT_STAGE_PRESETS` used to yield 800
774
+ * DPI, matching the vendor UI only by coincidence (the device happened to be
775
+ * on stage 1 of 6). Combine with `incottDecodeDpiStage` at `active` to get
776
+ * the actual DPI value — see `IncottHidClient.readStatus`.
777
+ *
778
+ * Byte 2 was then mistaken for a sub-command echo, because the count on the
779
+ * only device available is 6 and the driver happened to send `06`. It is
780
+ * data: `09 83 00` and a bare `09 83` both answer `06`. Matching it as an
781
+ * echo would reject every reply from a mouse whose cycle is not six stages
782
+ * long, so this decoder matches on the COMMAND ONLY — see
783
+ * `INCOTT_DPI_STAGE_COUNT_DEFAULT`.
784
+ */
785
+ export declare function incottDecodeDpiCycle(frame: Uint8Array): IncottDpiCycle | null;
786
+ /**
787
+ * `09 82 <stage>` -> the DPI value stored in that stage, little-endian at
788
+ * response bytes 3-4. This opcode used to be `INCOTT_CMD_UNKNOWN_82` — see
789
+ * the comment on `INCOTT_CMD_QUERY_DPI_STAGE_VALUE` for the hardware proof
790
+ * (six independent stage reads plus a write/read-back/restore round-trip on
791
+ * stage 2). `0x82` echoes its sub-command like `0x83`/`0x84`/`0x85`/`0x8e`
792
+ * (verified: `09 82 03` replies `09 82 03 …`), so `incottFrameMatches`
793
+ * checking byte 2 against `stage` is safe here.
794
+ */
795
+ export declare function incottDecodeDpiStage(frame: Uint8Array, stage: number): number | null;
796
+ /**
797
+ * One axis of one stage, from a reply to `incottEncodeQueryDpiAxis`. The
798
+ * requested axis MUST be matched at byte 8 — see `incottFrameMatches`.
799
+ */
800
+ export declare function incottDecodeDpiStageAxis(frame: Uint8Array, stage: number, axis: IncottDpiAxis): number | null;
801
+ /**
802
+ * The polling value sits in byte 2, mirroring the write, which also carries
803
+ * its value in the sub-command slot. CONFIRMED on hardware 2026-09-08: writing
804
+ * wire `1` then wire `0` and reading back showed byte 2 follow, `0 -> 1 -> 0`.
805
+ * `0x81` does NOT echo a sub-command the way `0x82`-`0x86`/`0x8e` do — byte 2
806
+ * here is data, not an echo — which is why it stays out of
807
+ * `SUB_ECHOING_QUERIES` in `src/drivers/incott/hid.ts`.
808
+ */
809
+ export declare function incottDecodePollingRate(frame: Uint8Array): number | null;
810
+ /**
811
+ * Reads lift-off from the packed byte 7 of the `0x84`/sub `0x00` response
812
+ * (high nibble). Superseded as the driver's primary read by
813
+ * `incottDecodeLiftOffDirect` (see `INCOTT_SUB_LOD`'s symmetric
814
+ * `0x84`/`0x01` read), which is clearer, but kept and still exercised: it was
815
+ * cross-checked against the symmetric read on hardware 2026-09-08 — hardware
816
+ * values 0, 1, 2 round-tripped identically through both forms — so this is
817
+ * not wrong, just less direct.
818
+ */
819
+ export declare function incottDecodeLiftOff(frame: Uint8Array): number | null;
820
+ /**
821
+ * Symmetric single-purpose read for lift-off: `09 84 01` -> response byte 3
822
+ * is the raw hardware value (0-2), matching the sub-command the `0x04`/`0x01`
823
+ * write uses (see `incottEncodeSetLiftOff`). PREFERRED over
824
+ * `incottDecodeLiftOff`'s packed byte-7 nibble read: verified on hardware
825
+ * 2026-09-08 by round-tripping hw 0, 1, 2 through both this form and the
826
+ * nibble form and finding they agree at every step. The hw-to-millimetre
827
+ * label mapping is still an open question — see `INCOTT_LOD_WIRE_TO_TENTHS`.
828
+ */
829
+ export declare function incottDecodeLiftOffDirect(frame: Uint8Array): number | null;
830
+ /**
831
+ * Reads motion sync from the packed byte 7 of the `0x84`/sub `0x00` response
832
+ * (low nibble). Superseded as the driver's primary read by
833
+ * `incottDecodeToggle(frame, INCOTT_SUB_MOTION_SYNC)` (the symmetric
834
+ * `0x84`/`0x04` read), which is clearer, but kept and still exercised: it was
835
+ * cross-checked against the symmetric read on hardware 2026-09-08 — 0/1/0
836
+ * round-tripped identically through both forms — so this is not wrong, just
837
+ * less direct.
838
+ */
839
+ export declare function incottDecodeMotionSync(frame: Uint8Array): boolean | null;
840
+ export declare function incottDecodeToggle(frame: Uint8Array, sub?: number): boolean | null;
841
+ /**
842
+ * `09 84 05` -> response byte 3 carries the current raw 0-2 performance-mode
843
+ * value. This follows the symmetric-read pattern every other `0x04`/`0x84`
844
+ * sensor sub-command uses (lift-off, ripple, angle snap and motion sync all
845
+ * pair a `0x04` write with an `0x84` read at the same sub-command), and
846
+ * `0x84` is already in the sub-echoing set (`SUB_ECHOING_QUERIES` in
847
+ * `src/drivers/incott/hid.ts`), so the existing transaction discipline covers
848
+ * it. Callers must still treat `null` as "unreadable," not as a confirmed
849
+ * value — see `IncottHidClient.setPowerMode`, which requires a non-null,
850
+ * matching read-back before reporting success.
851
+ */
852
+ export declare function incottDecodePerformanceMode(frame: Uint8Array): number | null;
853
+ export declare function incottDecodeDebounce(frame: Uint8Array): number | null;
854
+ export declare function incottDecodeSleep(frame: Uint8Array): number | null;
855
+ /** How a Fire Key button behaves: how many clicks it sends, and how fast. */
856
+ export interface IncottFireKey {
857
+ /** Clicks sent per press, 0-3. */
858
+ times: number;
859
+ /** Milliseconds between those clicks, 0-255. */
860
+ intervalMs: number;
861
+ }
862
+ /**
863
+ * `09 05 02 <times> <interval ms>` — see `INCOTT_SUB_FIRE_KEY`.
864
+ *
865
+ * These are the settings for whichever button is bound to "Rapid fire"; they
866
+ * are global to the device rather than per-button, since the command carries
867
+ * no button index.
868
+ */
869
+ export declare function incottEncodeSetFireKey(times: number, intervalMs: number): Uint8Array;
870
+ /** `09 85 02` -> times at byte 3, interval at byte 4. */
871
+ export declare function incottDecodeFireKey(frame: Uint8Array): IncottFireKey | null;
872
+ export declare function incottDecodeReceiverLed(frame: Uint8Array): number | null;
873
+ /**
874
+ * DISPROVEN AS A BATTERY READING, 2026-09-08 — kept as a codec only (its
875
+ * mechanical byte-6 decode is unchanged and still exercised by tests) and for
876
+ * `IncottHidClient.readStatus`'s regression test that battery is no longer
877
+ * sourced from this frame. See `INCOTT_CMD_QUERY_BATTERY` for the full
878
+ * write-up: a full charge cycle from roughly 60% to roughly 97% left this
879
+ * frame's byte 6 completely unchanged (`09 8e 01 5a 04 84 38 01`, `0x38` = 56
880
+ * throughout), the same disproof `0x89` byte 8 suffered earlier. Originally
881
+ * "proven" on hardware 2026-09-07 against a single static capture
882
+ * (`TX 09 8e 01` -> `RX 09 8e 01 5a 04 84 38 01 00`) that only ever showed one
883
+ * reading was never distinguished from a constant until the later
884
+ * full-cycle test. The real battery percentage is a field of the unsolicited
885
+ * input report the mouse emits while in use — see `incottDecodeInputStatus`
886
+ * and `IncottHidClient`'s class comment.
887
+ */
888
+ export declare function incottDecodeBattery(frame: Uint8Array): number | null;
889
+ /**
890
+ * Raw byte 1 (this module's convention — see below) of the mouse's
891
+ * unsolicited input report, above which the mouse is charging. At or below
892
+ * this, the raw byte IS the battery percentage; above it, subtract
893
+ * `INCOTT_INPUT_BATTERY_CHARGING_OFFSET` to get the percentage. See
894
+ * `incottDecodeInputStatus`.
895
+ */
896
+ export declare const INCOTT_INPUT_BATTERY_CHARGING_THRESHOLD = 100;
897
+ /** See `INCOTT_INPUT_BATTERY_CHARGING_THRESHOLD`. */
898
+ export declare const INCOTT_INPUT_BATTERY_CHARGING_OFFSET = 128;
899
+ /**
900
+ * Decoded fields of the mouse's unsolicited vendor-collection INPUT report
901
+ * (report id `INCOTT_INPUT_REPORT_ID`) — see `incottDecodeInputStatus`.
902
+ */
903
+ export interface IncottInputStatus {
904
+ /** 0-100. */
905
+ batteryPercent: number;
906
+ /** True when `byte0 > INCOTT_INPUT_BATTERY_CHARGING_THRESHOLD`. */
907
+ charging: boolean;
908
+ /** High nibble of byte 1: which of the six DPI stages is active (0-5). Corroborates, but does not replace, the `0x83`/`0x06` feature-report read. */
909
+ dpiStageIndex: number;
910
+ /** Low nibble of byte 1: index into `INCOTT_POLLING_WIRE_TO_HZ`. Corroborates, but does not replace, the `0x81` feature-report read. */
911
+ pollingIndex: number;
912
+ }
913
+ /**
914
+ * Decodes the mouse's UNSOLICITED input report — battery plus a packed
915
+ * DPI-stage/polling-rate snapshot. This is NOT a feature-report reply (no
916
+ * request triggers it): the device emits it on report id
917
+ * `INCOTT_INPUT_REPORT_ID` on its own, only while it is actively being used.
918
+ *
919
+ * BYTE-INDEX CONVENTION, mirroring the asymmetry this module's top-of-file
920
+ * comment already documents for feature reports (WebHID's `sendFeatureReport`
921
+ * takes the report id separately, so encoded payloads omit it, while
922
+ * `receiveFeatureReport` returns it at byte 0, so decoded frames include it):
923
+ * this function's `byte0`/`byte1` parameters EXCLUDE the report id, matching
924
+ * WebHID's `inputreport` event, whose `data` DataView excludes it too
925
+ * (`event.reportId` carries it separately). So `byte0` is
926
+ * `event.data.getUint8(0)`, `byte1` is `event.data.getUint8(1)`.
927
+ *
928
+ * node-hid's raw input buffer, by contrast, INCLUDES the report id at index
929
+ * 0 — the two hardware captures below were taken that way, so in node-hid
930
+ * terms `byte0` is `buf[1]` and `byte1` is `buf[2]`. Get this backwards and
931
+ * every field reads off by one byte. See
932
+ * `captures/incott-8k-wireless/input-report-battery.hex` and
933
+ * `src/drivers/incott/hid.ts`'s `onInputReport`, which unwraps the WebHID
934
+ * event into this convention before calling this function.
935
+ *
936
+ * Hardware-verified 2026-09-08 across a full charge cycle (~60% to ~97%):
937
+ * ```
938
+ * discharging: 09 5f 10 04 00 0f 0f 10 (node-hid) byte0=0x5f=95 -> 95%
939
+ * charging: 09 e1 10 04 00 0f 0f 10 (node-hid) byte0=0xe1=225 -> charging, 225-128=97%
940
+ * ```
941
+ * `raw > 100` means charging (subtract `INCOTT_INPUT_BATTERY_CHARGING_OFFSET`
942
+ * for the percent); `raw <= 100` means discharging (raw IS the percent). This
943
+ * is the same convention IncottHIDApp's `parseStatus` uses, and unlike that
944
+ * project's other claims, this one is now independently hardware-verified in
945
+ * both states — see `docs/incott-testing.md`.
946
+ *
947
+ * Byte 1's `0x10` on the unit under test decoded to DPI stage 1 / polling
948
+ * index 0, and both independently matched what the feature reads returned at
949
+ * the same moment (`09 83 06` -> stage 1, `09 81` byte 2 -> 0) — a
950
+ * corroborating cross-check only; `IncottHidClient` still treats the feature
951
+ * reads as authoritative for DPI stage and polling rate.
952
+ *
953
+ * Returns `null` when either byte is out of range, or when the derived
954
+ * percent would fall outside 0-100 (a malformed or unrelated report).
955
+ */
956
+ export declare function incottDecodeInputStatus(byte0: number, byte1: number): IncottInputStatus | null;
957
+ /**
958
+ * A button's current binding: the raw 32-bit action word, plus the label
959
+ * when it is one this driver knows.
960
+ *
961
+ * `label` is null for a binding the action table does not cover — a keyboard
962
+ * key, a macro, or an action from a model this contributor cannot test. The
963
+ * `code` is always reported so an unrecognised binding round-trips
964
+ * unchanged rather than being flattened to a default.
965
+ */
966
+ export interface IncottButtonBinding {
967
+ button: number;
968
+ code: number;
969
+ label: string | null;
970
+ }
971
+ /**
972
+ * `09 86 <button 0..5>` -> response bytes 3-6 = the binding, 32-bit
973
+ * little-endian.
974
+ *
975
+ * PREVIOUSLY A BUG: this read only bytes 3-5 and reported them as three
976
+ * unnamed bytes, silently truncating the top byte. Every action in
977
+ * `INCOTT_BUTTON_ACTIONS` whose code exceeds 24 bits — "Rapid fire"
978
+ * (`0x0218F00A`) among them — decoded to a different value than was
979
+ * written. The vendor reads the same four bytes
980
+ * (`rData[5]<<24|rData[4]<<16|rData[3]<<8|rData[2]`).
981
+ */
982
+ export declare function incottDecodeButtonBinding(frame: Uint8Array, button: number): IncottButtonBinding | null;
983
+ /**
984
+ * Decodes the identity reply (`09 8f 00` -> `09 8f 01 0e 02 f0 f1 00 ff`).
985
+ *
986
+ * Byte map, transcribed from the vendor configurator's `readDps()` and
987
+ * confirmed byte-for-byte against this contributor's G23V2 (capture
988
+ * 2026-09-07, `captures/incott-8k-wireless/query-sweep-0x80-0x8f.hex`):
989
+ *
990
+ * byte 2 guard, always 0x01 -- the vendor abandons the device otherwise
991
+ * byte 3 model code -- 0x0e = G23V2, see INCOTT_MODEL_BY_CODE
992
+ * byte 4 receiver type -- 0x02 = 8 KHz receiver
993
+ * byte 5 sensor slot A -- 0xF0 -> PAW3395, 0xF1 -> PAW3950
994
+ * byte 6 sensor slot B -- same encoding, 0x00 when unpopulated
995
+ *
996
+ * THE SENSOR SLOT MOVES WITH THE RECEIVER, so neither byte alone is "the"
997
+ * sensor. Two wired captures of the same mouse:
998
+ *
999
+ * cable + dongle (2026-09-08): 09 8f 01 0e 02 f0 f1 00 ff
1000
+ * cable only (2026-09-11): 09 8f 01 0e 00 f1 00 00 00
1001
+ *
1002
+ * With the dongle present, byte 4 reports the receiver and the `0xF1` sits at
1003
+ * byte 6; with the dongle gone, byte 4 is `0x00` and the same `0xF1` sits at
1004
+ * byte 5. This is why the vendor indexes by connection
1005
+ * (`let i = this.iswireless ? 5 : 4` over its report-id-less buffer, i.e.
1006
+ * frame bytes 6:5) — that is correct behaviour, not the cosmetic bug an
1007
+ * earlier version of this comment claimed.
1008
+ *
1009
+ * WHY ANY SLOT, NOT THE CONNECTION-INDEXED ONE: the fitted sensor is settled
1010
+ * independently of this frame. A PAW3395 stops at 32000 DPI in the vendor's
1011
+ * own table, and this mouse stored and read back 45000 over the CABLE
1012
+ * (`captures/incott-8k-wireless/wired-dpi-ceiling-2026-09-11.hex`). It is a
1013
+ * PAW3950 on every link, so the answer is whichever slot carries `0xF1`. The
1014
+ * vendor's index disagrees in exactly one configuration — cable AND dongle
1015
+ * attached, where it reads byte 5's `0xF0` and drops the "Pro" — and that is
1016
+ * the one case where a capability byte cannot be describing this mouse.
1017
+ *
1018
+ * The same capture also shows there is NO wired DPI ceiling to model: 45000
1019
+ * is accepted over the cable, so `INCOTT_DPI_MAX` stays flat across links,
1020
+ * unlike the polling rate (`INCOTT_POLLING_STEPS_HZ_WIRED`).
1021
+ *
1022
+ * Returns `null` ONLY when the report id or command echo is wrong — `open()`
1023
+ * uses that as its collection-liveness probe. A frame that is well-formed
1024
+ * but too short, or whose guard byte is not `0x01`, still yields an identity
1025
+ * carrying `raw` with every decoded field left null: an unreadable model is
1026
+ * reported as unknown, never guessed.
1027
+ */
1028
+ export declare function incottDecodeIdentity(frame: Uint8Array): IncottDeviceIdentity | null;
1029
+ /**
1030
+ * True when this product id is the WIRED one (`0x622C`) rather than the 2.4
1031
+ * GHz dongle's (`0x522C`, `INCOTT_PRODUCT_ID`) — hardware-verified 2026-09-08,
1032
+ * see `INCOTT_PRODUCT_ID_WIRED`. Formerly `incottIsChargingProduct`: it
1033
+ * always returned exactly this, but under a name that mislabelled the
1034
+ * connection as a charging flag. Charging is real for this product id, but
1035
+ * it is a CONSEQUENCE of being plugged in, not what the id itself encodes —
1036
+ * see `IncottHidClient.readStatus`, which now sets `connectionType` from
1037
+ * this helper directly and derives `batteryState: "Charging"` from it rather
1038
+ * than from a same-named constant.
1039
+ */
1040
+ export declare function incottIsWiredProduct(productId: number): boolean;
1041
+ /**
1042
+ * Tidies the raw HID product string for display: drops a single leading
1043
+ * vendor word ("incott") and a single trailing "mouse", case-insensitively,
1044
+ * leaving whatever sits between. Falls back to the untouched raw string if
1045
+ * stripping both would leave nothing.
1046
+ *
1047
+ * "incott Esports G23V2Pro mouse" -> "Esports G23V2Pro"
1048
+ * "incott 8K wireless mouse" -> "8K wireless"
1049
+ *
1050
+ * WHY THIS EXISTS: the product string names a model only over the CABLE
1051
+ * ("incott Esports G23V2Pro mouse", hardware-verified 2026-09-08); the
1052
+ * wireless dongle reports a generic "incott 8K wireless mouse" with no model
1053
+ * in it at all. This function only TIDIES whatever raw string the device
1054
+ * actually reported; it never invents one.
1055
+ *
1056
+ * This is now the FALLBACK, not the primary source. The identity reply's
1057
+ * byte layout has since been decoded (`incottDecodeIdentity`), so
1058
+ * `IncottHidClient.readStatus` prefers the model read from the device —
1059
+ * which works wirelessly too — and drops back to this function only when the
1060
+ * identity query fails or reports a model code the table does not know.
1061
+ */
1062
+ export declare function incottNormalizeProductName(raw: string): string;
1063
+ /** Maps the lift-off wire value (in tenths of a millimetre) to the shared Low/Medium/High stops. */
1064
+ export declare function incottLiftOffLabel(tenthsMm: number): "Low" | "Medium" | "High" | null;
1065
+ /** Maps a Low/Medium/High stop back to tenths of a millimetre for `incottEncodeSetLiftOff`. */
1066
+ export declare function incottLiftOffTenths(level: "Low" | "Medium" | "High"): number;
1067
+ //# sourceMappingURL=index.d.ts.map