@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,680 @@
1
+ import { NINJUTSO_COMMAND, NINJUTSO_CONTROL_PAYLOAD_LENGTH, NINJUTSO_CONTROL_REPORT_ID, NINJUTSO_LEGACY_MOUSE_PRODUCT_IDS, NINJUTSO_LEGACY_PAYLOAD_LENGTH, NINJUTSO_LEGACY_RECEIVER_PRODUCT_IDS, NINJUTSO_LEGACY_REPORT_ID, NINJUTSO_LEGACY_VENDOR_ID, NINJUTSO_MOUSE_PRODUCT_IDS, NINJUTSO_POLLING_RATES, NINJUTSO_RECEIVER_PRODUCT_IDS, NINJUTSO_REPORT_ID, NINJUTSO_VENDOR_ID, ninjutsoBuildRequest, ninjutsoDecodeDpi, ninjutsoDecodePollingRate, ninjutsoEncodeDpi, ninjutsoEncodePollingRate, ninjutsoLegacyDecodeDpi, ninjutsoLegacyEncodeDpi, ninjutsoLegacyRequest, ninjutsoResponseValue, } from "@openmouse/protocol/ninjutso";
2
+ const CURRENT_IDS = new Set([...NINJUTSO_MOUSE_PRODUCT_IDS, ...NINJUTSO_RECEIVER_PRODUCT_IDS]);
3
+ const LEGACY_IDS = new Set([...NINJUTSO_LEGACY_MOUSE_PRODUCT_IDS, ...NINJUTSO_LEGACY_RECEIVER_PRODUCT_IDS]);
4
+ const CURRENT_RECEIVERS = new Set(NINJUTSO_RECEIVER_PRODUCT_IDS);
5
+ const LEGACY_RECEIVERS = new Set(NINJUTSO_LEGACY_RECEIVER_PRODUCT_IDS);
6
+ const SORA_V3_IDS = new Set([0xe010, 0xeb02]);
7
+ const SORA_V2_3950_IDS = new Set([0xae14, 0xae15, 0xae16]);
8
+ const LEGACY_HIGH_RATE_RECEIVERS = new Set([0xae8c, 0xae8a]);
9
+ const LOD_VALUES = ["Low", "Medium", "High"];
10
+ const SLEEP_OPTIONS = Array.from({ length: 15 }, (_, index) => (index + 1) * 60);
11
+ const SYSTEM_MODES = ["High Speed", "Competitive", "Ultra"];
12
+ const SLAM_CLICK_LEVELS = ["Low", "Medium", "High"];
13
+ class NinjutsoCommandTimeoutError extends Error {
14
+ }
15
+ /**
16
+ * NinjaForce-derived WebHID implementation for Sora V2/V3 and TEN-family mice.
17
+ * Packet layouts are public and deterministic; hardware verification is still pending.
18
+ */
19
+ export class NinjutsoHidClient {
20
+ canDisableSleep = false;
21
+ device;
22
+ queue = Promise.resolve();
23
+ lastStatus = null;
24
+ profile = 1;
25
+ effectiveProductId = null;
26
+ constructor(device) {
27
+ this.device = device;
28
+ }
29
+ static isSupported(device) {
30
+ if (device.vendorId === NINJUTSO_VENDOR_ID && CURRENT_IDS.has(device.productId)) {
31
+ return hasFeatureReport(device.collections, NINJUTSO_REPORT_ID);
32
+ }
33
+ if (device.vendorId === NINJUTSO_LEGACY_VENDOR_ID && LEGACY_IDS.has(device.productId)) {
34
+ return hasFeatureReport(device.collections, NINJUTSO_LEGACY_REPORT_ID)
35
+ && hasFeatureReport(device.collections, 4);
36
+ }
37
+ return false;
38
+ }
39
+ get pollIntervalMs() {
40
+ return this.isWireless() ? 10_000 : 30_000;
41
+ }
42
+ async open() {
43
+ if (!this.device.opened)
44
+ await this.device.open();
45
+ }
46
+ async close() {
47
+ this.lastStatus = null;
48
+ this.effectiveProductId = null;
49
+ if (this.device.opened)
50
+ await this.device.close();
51
+ }
52
+ async startNotifications(_onChange) {
53
+ return false;
54
+ }
55
+ isLegacy() {
56
+ return this.device.vendorId === NINJUTSO_LEGACY_VENDOR_ID;
57
+ }
58
+ isWireless() {
59
+ return (this.isLegacy() ? LEGACY_RECEIVERS : CURRENT_RECEIVERS).has(this.device.productId);
60
+ }
61
+ displayName() {
62
+ if (this.isWireless() && this.effectiveProductId !== null) {
63
+ if (this.isLegacy())
64
+ return "Ninjutso Sora V2";
65
+ return SORA_V3_IDS.has(this.effectiveProductId) ? "Ninjutso Sora V3" : "Ninjutso TEN / TEN AIR";
66
+ }
67
+ const reported = this.device.productName?.trim();
68
+ if (reported && !/^usb (input|hid)/i.test(reported))
69
+ return reported;
70
+ if (this.isLegacy())
71
+ return "Ninjutso Sora V2";
72
+ if (SORA_V3_IDS.has(this.effectiveProductId ?? this.device.productId))
73
+ return "Ninjutso Sora V3";
74
+ return "Ninjutso TEN / TEN AIR";
75
+ }
76
+ getDpiOptions() {
77
+ const direct = !this.isLegacy() && SORA_V3_IDS.has(this.effectiveProductId ?? this.device.productId);
78
+ const max = direct ? 45_000 : this.isLegacy() ? 30_000 : 30_000;
79
+ const step = direct ? 1 : 50;
80
+ return Array.from({ length: Math.floor(max / step) }, (_, index) => (index + 1) * step);
81
+ }
82
+ getSupportedPollingRates() {
83
+ if (!this.isLegacy())
84
+ return [...NINJUTSO_POLLING_RATES];
85
+ return LEGACY_HIGH_RATE_RECEIVERS.has(this.device.productId) ? [1000, 2000, 4000, 8000] : [1000];
86
+ }
87
+ getSleepOptions() {
88
+ return this.isLegacy() ? [] : SLEEP_OPTIONS;
89
+ }
90
+ getDebounceMaxMs() {
91
+ // NinjaForce exposes this byte as three Slam-Click levels, not milliseconds.
92
+ return 0;
93
+ }
94
+ async readStatus(_live = false) {
95
+ return await this.run(async () => {
96
+ await this.open();
97
+ const status = this.isLegacy() ? await this.readLegacyStatus() : await this.readCurrentStatus();
98
+ this.lastStatus = status;
99
+ return status;
100
+ });
101
+ }
102
+ async setDpi(dpi) {
103
+ return await this.run(async () => {
104
+ await this.open();
105
+ return this.isLegacy() ? await this.setLegacyDpi(dpi) : await this.setCurrentDpi(dpi);
106
+ });
107
+ }
108
+ async setPollingRate(rate) {
109
+ return await this.run(async () => {
110
+ await this.open();
111
+ if (!this.getSupportedPollingRates().includes(rate))
112
+ throw new Error(`This Ninjutso connection does not support ${rate} Hz.`);
113
+ if (this.isLegacy()) {
114
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(ninjutsoLegacyRequest(10, this.profile, Math.log2(rate / 1000))));
115
+ const confirmed = this.legacyRate((await this.readLegacySettings()).data[24]);
116
+ if (confirmed !== rate)
117
+ throw new Error(`The mouse kept ${confirmed} Hz instead of ${rate} Hz.`);
118
+ this.patch({ pollingRateHz: confirmed });
119
+ return confirmed;
120
+ }
121
+ await this.sendCurrent(NINJUTSO_COMMAND.setPollingRate, [ninjutsoEncodePollingRate(rate)]);
122
+ const confirmed = ninjutsoDecodePollingRate((await this.readCurrent(NINJUTSO_COMMAND.pollingRate))[0]) ?? 0;
123
+ if (confirmed !== rate)
124
+ throw new Error(`The mouse kept ${confirmed} Hz instead of ${rate} Hz.`);
125
+ this.patch({ pollingRateHz: confirmed });
126
+ return confirmed;
127
+ });
128
+ }
129
+ async setLiftOffDistance(value) {
130
+ return await this.run(async () => {
131
+ await this.open();
132
+ const code = LOD_VALUES.indexOf(value);
133
+ if (code < 0)
134
+ throw new Error(`Unsupported lift-off distance: ${value}.`);
135
+ if (this.isLegacy()) {
136
+ const effective = await this.ensureEffectiveProductId();
137
+ if (!SORA_V2_3950_IDS.has(effective) && code === 0)
138
+ throw new Error("This Sora V2 supports Medium or High lift-off distance only.");
139
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(ninjutsoLegacyRequest(11, this.profile, code)));
140
+ const confirmed = this.decodeLod((await this.readLegacySettings()).data[22]);
141
+ if (confirmed !== value)
142
+ throw new Error(`The mouse kept ${confirmed} lift-off distance instead of ${value}.`);
143
+ this.patch({ liftOffDistance: confirmed });
144
+ return confirmed;
145
+ }
146
+ await this.sendCurrent(NINJUTSO_COMMAND.setLiftOffDistance, [code]);
147
+ const confirmed = this.decodeLod((await this.readCurrent(NINJUTSO_COMMAND.liftOffDistance))[0]);
148
+ if (confirmed !== value)
149
+ throw new Error(`The mouse kept ${confirmed} lift-off distance instead of ${value}.`);
150
+ this.patch({ liftOffDistance: confirmed });
151
+ return confirmed;
152
+ });
153
+ }
154
+ async setMotionSync(enabled) {
155
+ return await this.run(async () => {
156
+ await this.open();
157
+ if (this.isLegacy()) {
158
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(ninjutsoLegacyRequest(6, this.profile, enabled ? 1 : 0)));
159
+ const confirmed = (await this.readLegacySettings()).data[23] === 1;
160
+ if (confirmed !== enabled)
161
+ throw new Error(`The mouse left Motion Sync ${confirmed ? "on" : "off"}.`);
162
+ this.patch({ motionSync: confirmed });
163
+ return confirmed;
164
+ }
165
+ await this.sendCurrent(NINJUTSO_COMMAND.setMotionSync, [enabled ? 1 : 0]);
166
+ const confirmed = (await this.readCurrent(NINJUTSO_COMMAND.motionSync))[0] === 1;
167
+ if (confirmed !== enabled)
168
+ throw new Error(`The mouse left Motion Sync ${confirmed ? "on" : "off"}.`);
169
+ this.patch({ motionSync: confirmed });
170
+ return confirmed;
171
+ });
172
+ }
173
+ async setSleepTimeout(seconds) {
174
+ return await this.run(async () => {
175
+ if (this.isLegacy())
176
+ throw new Error("Sora V2 does not expose a sleep timer in NinjaForce.");
177
+ if (!Number.isInteger(seconds) || seconds < 60 || seconds > 900 || seconds % 60 !== 0) {
178
+ throw new Error("Ninjutso sleep timeout must be 1–15 minutes.");
179
+ }
180
+ await this.open();
181
+ await this.sendCurrent(NINJUTSO_COMMAND.setSleepMinutes, [seconds / 60]);
182
+ const confirmed = (await this.readCurrent(NINJUTSO_COMMAND.sleepMinutes))[0] * 60;
183
+ if (confirmed !== seconds)
184
+ throw new Error(`The mouse kept a ${confirmed} second sleep timeout instead of ${seconds}.`);
185
+ this.patch({ sleepTimeout: confirmed });
186
+ return confirmed;
187
+ });
188
+ }
189
+ async setNinjutsoSystemMode(mode) {
190
+ return await this.run(async () => {
191
+ await this.open();
192
+ const direct = SORA_V3_IDS.has(await this.ensureEffectiveProductId());
193
+ const code = SYSTEM_MODES.indexOf(mode);
194
+ if (code < 0 || (!direct && code > 1))
195
+ throw new Error(`${this.displayName()} does not support ${mode} mode.`);
196
+ if (this.isLegacy()) {
197
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(ninjutsoLegacyRequest(23, this.profile, code + 1)));
198
+ const confirmed = SYSTEM_MODES[Math.max(0, ((await this.readLegacySettings()).data[21] ?? 1) - 1)] ?? "High Speed";
199
+ if (confirmed !== mode)
200
+ throw new Error(`The mouse kept ${confirmed} mode instead of ${mode}.`);
201
+ }
202
+ else {
203
+ await this.sendCurrent(NINJUTSO_COMMAND.setSystemMode, [code]);
204
+ const confirmed = SYSTEM_MODES[(await this.readCurrent(NINJUTSO_COMMAND.systemMode))[0]] ?? "High Speed";
205
+ if (confirmed !== mode)
206
+ throw new Error(`The mouse kept ${confirmed} mode instead of ${mode}.`);
207
+ }
208
+ this.patch({ ninjutsoSystemMode: mode });
209
+ return mode;
210
+ });
211
+ }
212
+ async setNinjutsoHyperClick(enabled) {
213
+ return await this.setCurrentOption("HyperClick", NINJUTSO_COMMAND.setHyperClick, NINJUTSO_COMMAND.hyperClick, enabled, "ninjutsoHyperClick");
214
+ }
215
+ async setNinjutsoOpticalEngine(mode) {
216
+ return await this.run(async () => {
217
+ await this.open();
218
+ if (this.isLegacy() || !SORA_V3_IDS.has(await this.ensureEffectiveProductId()))
219
+ throw new Error("Optical Engine modes are only available on Sora V3.");
220
+ await this.sendCurrent(NINJUTSO_COMMAND.setOpticalEngine, [mode === "Burst" ? 1 : 0]);
221
+ const confirmed = (await this.readCurrent(NINJUTSO_COMMAND.opticalEngine))[0] === 1 ? "Burst" : "Standard";
222
+ if (confirmed !== mode)
223
+ throw new Error(`The mouse kept ${confirmed} optical mode instead of ${mode}.`);
224
+ this.patch({ ninjutsoOpticalEngine: confirmed });
225
+ return confirmed;
226
+ });
227
+ }
228
+ async setNinjutsoSlamClick(level) {
229
+ return await this.run(async () => {
230
+ await this.open();
231
+ const code = SLAM_CLICK_LEVELS.indexOf(level);
232
+ if (code < 0)
233
+ throw new Error(`Unsupported Slam-Click level: ${level}.`);
234
+ if (this.isLegacy()) {
235
+ const request = ninjutsoLegacyRequest(36, this.profile, code);
236
+ request[6] = 1;
237
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(request));
238
+ const confirmed = SLAM_CLICK_LEVELS[(await this.readLegacySettings()).data[25]] ?? "Medium";
239
+ if (confirmed !== level)
240
+ throw new Error(`The mouse kept ${confirmed} Slam-Click instead of ${level}.`);
241
+ }
242
+ else {
243
+ await this.sendCurrent(NINJUTSO_COMMAND.setSlamClick, [code]);
244
+ const confirmed = SLAM_CLICK_LEVELS[(await this.readCurrent(NINJUTSO_COMMAND.slamClick))[0]] ?? "Medium";
245
+ if (confirmed !== level)
246
+ throw new Error(`The mouse kept ${confirmed} Slam-Click instead of ${level}.`);
247
+ }
248
+ this.patch({ ninjutsoSlamClick: level });
249
+ return level;
250
+ });
251
+ }
252
+ async setNinjutsoActiveDpiStage(stage) {
253
+ return await this.run(async () => {
254
+ await this.open();
255
+ if (!Number.isInteger(stage) || stage < 0 || stage > 3)
256
+ throw new Error("DPI stage must be between 1 and 4.");
257
+ if (this.isLegacy()) {
258
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(ninjutsoLegacyRequest(14, this.profile, stage)));
259
+ const settings = await this.readLegacySettings();
260
+ const confirmed = settings.data[20] ?? 0;
261
+ if (confirmed !== stage)
262
+ throw new Error(`The mouse kept DPI stage ${confirmed + 1}.`);
263
+ const offset = 12 + stage * 2;
264
+ this.patch({ activeDpiStage: stage, dpi: ninjutsoLegacyDecodeDpi(settings.data[offset], settings.data[offset + 1]) });
265
+ }
266
+ else {
267
+ await this.sendCurrent(NINJUTSO_COMMAND.setActiveDpiStage, [stage]);
268
+ const confirmed = (await this.readCurrent(NINJUTSO_COMMAND.activeDpiStage))[0] ?? 0;
269
+ if (confirmed !== stage)
270
+ throw new Error(`The mouse kept DPI stage ${confirmed + 1}.`);
271
+ const direct = SORA_V3_IDS.has(await this.ensureEffectiveProductId());
272
+ const dpi = await this.readCurrent(NINJUTSO_COMMAND.dpi, [stage]);
273
+ this.patch({ activeDpiStage: stage, dpi: ninjutsoDecodeDpi(dpi[0], dpi[1], dpi[2], direct) });
274
+ }
275
+ return stage;
276
+ });
277
+ }
278
+ async setLighting(lighting) {
279
+ return await this.run(async () => {
280
+ await this.open();
281
+ if (this.isLegacy() || !this.isWireless())
282
+ throw new Error("Receiver lighting is not available on this connection.");
283
+ const modeCodes = { Static: 1, Cycling: 2, Wave: 3 };
284
+ if (lighting.mode === "Off")
285
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingState, [0]);
286
+ else {
287
+ const mode = lighting.mode;
288
+ const code = mode ? modeCodes[mode] : undefined;
289
+ if (!code)
290
+ throw new Error(`Unsupported receiver lighting mode: ${lighting.mode}.`);
291
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingState, [1]);
292
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingMode, [code]);
293
+ if (lighting.color && mode && lighting.colorModes.includes(mode)) {
294
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingColor, this.hexToRgb(lighting.color));
295
+ }
296
+ if (mode && lighting.reactiveModes.includes(mode) && lighting.speed !== null) {
297
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingSpeed, [20 - lighting.speed]);
298
+ }
299
+ if (lighting.brightness != null && lighting.brightnessLevels?.includes(lighting.brightness)) {
300
+ await this.sendCurrent(NINJUTSO_COMMAND.setLightingBrightness, [lighting.brightness / 25]);
301
+ }
302
+ }
303
+ const confirmed = await this.readCurrentLighting(SORA_V3_IDS.has(await this.ensureEffectiveProductId()));
304
+ if (!confirmed)
305
+ throw new Error("The receiver did not confirm its lighting settings.");
306
+ this.patch({ lighting: confirmed });
307
+ return confirmed;
308
+ });
309
+ }
310
+ async readCurrentStatus() {
311
+ const effective = await this.ensureEffectiveProductId();
312
+ this.profile = (await this.readCurrent(NINJUTSO_COMMAND.profile))[0] || 1;
313
+ const stage = (await this.readCurrent(NINJUTSO_COMMAND.activeDpiStage))[0] ?? 0;
314
+ const direct = SORA_V3_IDS.has(effective);
315
+ // Feature replies share one report id, so keep request/response pairs ordered.
316
+ const battery = await this.readCurrent(NINJUTSO_COMMAND.batteryPercent);
317
+ const charging = await this.readCurrent(NINJUTSO_COMMAND.batteryCharging);
318
+ const dpi = await this.readCurrent(NINJUTSO_COMMAND.dpi, [stage]);
319
+ const polling = await this.readCurrent(NINJUTSO_COMMAND.pollingRate);
320
+ const lod = await this.readCurrent(NINJUTSO_COMMAND.liftOffDistance);
321
+ // Some Sora V3 firmware does not implement command 0x0e even though the
322
+ // shared NinjaForce UI probes it. Treat that as a missing capability rather
323
+ // than preventing every supported setting from loading.
324
+ const motion = await this.readCurrentOptional(NINJUTSO_COMMAND.motionSync);
325
+ const angle = await this.readCurrentOptional(NINJUTSO_COMMAND.angleTuning);
326
+ const sleep = await this.readCurrentOptional(NINJUTSO_COMMAND.sleepMinutes);
327
+ const stageCountReply = await this.readCurrentOptional(NINJUTSO_COMMAND.dpiStageCount);
328
+ const system = await this.readCurrentOptional(NINJUTSO_COMMAND.systemMode);
329
+ const hyper = await this.readCurrentOptional(NINJUTSO_COMMAND.hyperClick);
330
+ const slam = await this.readCurrentOptional(NINJUTSO_COMMAND.slamClick);
331
+ const optical = direct ? await this.readCurrentOptional(NINJUTSO_COMMAND.opticalEngine) : null;
332
+ const stageCount = Math.min(Math.max(stageCountReply?.[0] ?? 1, 1), 4);
333
+ const dpiStages = [];
334
+ for (let index = 0; index < stageCount; index++) {
335
+ const value = index === stage ? dpi : await this.readCurrentOptional(NINJUTSO_COMMAND.dpi, [index]);
336
+ if (!value)
337
+ break;
338
+ dpiStages.push(ninjutsoDecodeDpi(value[0], value[1], value[2], direct));
339
+ }
340
+ const lighting = this.isWireless() ? await this.readCurrentLighting(direct) : null;
341
+ const firmware = await this.readCurrentOptional(NINJUTSO_COMMAND.firmware, [0]);
342
+ const batteryPercent = Math.min(battery[0] ?? 0, 100);
343
+ const firmwareValues = firmware ? [`Mouse ${this.decodeFirmware(firmware)}`] : [];
344
+ if (this.isWireless()) {
345
+ const receiverVersion = await this.readCurrentOptional(NINJUTSO_COMMAND.firmware, [1]);
346
+ if (receiverVersion)
347
+ firmwareValues.push(`Receiver ${this.decodeFirmware(receiverVersion)}`);
348
+ }
349
+ const pollingRateHz = ninjutsoDecodePollingRate(polling[0]) ?? 1000;
350
+ const supportedLiftOffDistances = [...LOD_VALUES];
351
+ return {
352
+ brand: "Ninjutso",
353
+ name: this.displayName(),
354
+ ui: {
355
+ family: "ninjutso",
356
+ hideUnsupportedPollingRates: true,
357
+ hideSignalCard: true,
358
+ hideSleepCard: sleep === null,
359
+ hideMotionSync: motion === null,
360
+ hideAngleSnapping: true,
361
+ hideRippleControl: true,
362
+ showAdvancedSection: true,
363
+ forceShowBattery: true,
364
+ defaultDisplayName: this.displayName(),
365
+ pollingNote: "NinjaForce exposes 1,000–8,000 Hz on this protocol.",
366
+ },
367
+ batteryPercent,
368
+ batteryState: charging[0] ? "Charging" : "Discharging",
369
+ dpi: ninjutsoDecodeDpi(dpi[0], dpi[1], dpi[2], direct),
370
+ dpiStages: dpiStages.length ? dpiStages : undefined,
371
+ activeDpiStage: stage,
372
+ pollingRateHz,
373
+ supportedPollingRates: [...NINJUTSO_POLLING_RATES],
374
+ activeProfile: this.profile,
375
+ connectionType: this.isWireless() ? "Wireless" : "Wired",
376
+ connectionDetail: this.isWireless() ? "2.4 GHz receiver · NinjaForce protocol" : "USB · NinjaForce protocol",
377
+ motionSync: motion === null ? null : motion[0] === 1,
378
+ ninjutsoSystemMode: system ? SYSTEM_MODES[system[0]] ?? null : null,
379
+ ninjutsoSystemModes: system ? [...SYSTEM_MODES.slice(0, direct ? 3 : 2)] : undefined,
380
+ ninjutsoHyperClick: hyper ? hyper[0] === 1 : null,
381
+ ninjutsoOpticalEngine: optical ? optical[0] === 1 ? "Burst" : "Standard" : null,
382
+ ninjutsoSlamClick: slam ? SLAM_CLICK_LEVELS[slam[0]] ?? null : null,
383
+ debounceMs: null,
384
+ sleepTimeout: sleep === null ? null : (sleep[0] ?? 0) * 60 || null,
385
+ angleTuning: angle === null ? null : this.signedByte(angle[0] ?? 0),
386
+ angleSnapping: null,
387
+ rippleControl: null,
388
+ liftOffDistance: this.decodeLod(lod[0]),
389
+ supportedLiftOffDistances,
390
+ lighting: lighting ?? undefined,
391
+ firmware: firmwareValues,
392
+ };
393
+ }
394
+ async readLegacyStatus() {
395
+ const effective = await this.ensureEffectiveProductId();
396
+ const settings = await this.readLegacySettings();
397
+ const data = settings.data;
398
+ this.profile = settings.profile;
399
+ const stageCount = Math.min(Math.max(data[11] ?? 1, 1), 4);
400
+ const stage = Math.min(data[20] ?? 0, stageCount - 1);
401
+ const dpiOffset = 12 + stage * 2;
402
+ const rate = LEGACY_HIGH_RATE_RECEIVERS.has(this.device.productId) ? this.legacyRate(data[24] ?? 0) : 1000;
403
+ const supportsUltraLow = SORA_V2_3950_IDS.has(effective);
404
+ return {
405
+ brand: "Ninjutso",
406
+ name: this.displayName(),
407
+ ui: {
408
+ family: "ninjutso",
409
+ hideUnsupportedPollingRates: true,
410
+ hideSignalCard: true,
411
+ hideSleepCard: true,
412
+ hideAngleSnapping: true,
413
+ hideRippleControl: true,
414
+ showAdvancedSection: true,
415
+ forceShowBattery: true,
416
+ defaultDisplayName: "Ninjutso Sora V2",
417
+ pollingNote: "Polling options follow the connected Sora V2 receiver generation.",
418
+ },
419
+ batteryPercent: Math.min(data[7] ?? 0, 100),
420
+ batteryState: this.isWireless() ? data[8] === 1 ? "Charging" : "Discharging" : "Unknown",
421
+ dpi: ninjutsoLegacyDecodeDpi(data[dpiOffset], data[dpiOffset + 1]),
422
+ dpiStages: Array.from({ length: stageCount }, (_, index) => ninjutsoLegacyDecodeDpi(data[12 + index * 2], data[13 + index * 2])),
423
+ activeDpiStage: stage,
424
+ pollingRateHz: rate,
425
+ supportedPollingRates: this.getSupportedPollingRates(),
426
+ activeProfile: this.profile,
427
+ connectionType: this.isWireless() ? "Wireless" : "Wired",
428
+ connectionDetail: this.isWireless() ? "2.4 GHz receiver · Sora V2 protocol" : "USB · Sora V2 protocol",
429
+ motionSync: data[23] === 1,
430
+ ninjutsoSystemMode: SYSTEM_MODES[Math.max(0, (data[21] ?? 1) - 1)] ?? "High Speed",
431
+ ninjutsoSystemModes: ["High Speed", "Competitive"],
432
+ ninjutsoSlamClick: SLAM_CLICK_LEVELS[data[25]] ?? "Medium",
433
+ debounceMs: null,
434
+ sleepTimeout: null,
435
+ angleTuning: supportsUltraLow ? this.signedByte(data[26] ?? 0) : null,
436
+ angleSnapping: null,
437
+ rippleControl: null,
438
+ liftOffDistance: this.decodeLod(data[22]),
439
+ supportedLiftOffDistances: supportsUltraLow ? [...LOD_VALUES] : ["Medium", "High"],
440
+ firmware: await this.readLegacyFirmware(),
441
+ };
442
+ }
443
+ async setCurrentDpi(dpi) {
444
+ const effective = await this.ensureEffectiveProductId();
445
+ this.profile = (await this.readCurrent(NINJUTSO_COMMAND.profile))[0] || 1;
446
+ const stage = (await this.readCurrent(NINJUTSO_COMMAND.activeDpiStage))[0] ?? 0;
447
+ const direct = SORA_V3_IDS.has(effective);
448
+ const encoded = ninjutsoEncodeDpi(dpi, direct);
449
+ await this.setControl(false);
450
+ try {
451
+ await this.sendCurrent(NINJUTSO_COMMAND.setDpi, [stage, ...encoded]);
452
+ }
453
+ finally {
454
+ await this.setControl(true);
455
+ }
456
+ const value = await this.readCurrent(NINJUTSO_COMMAND.dpi, [stage]);
457
+ const confirmed = ninjutsoDecodeDpi(value[0], value[1], value[2], direct);
458
+ if (confirmed !== dpi)
459
+ throw new Error(`The mouse kept ${confirmed} DPI instead of ${dpi} DPI.`);
460
+ const dpiStages = this.lastStatus?.dpiStages?.slice();
461
+ if (dpiStages)
462
+ dpiStages[stage] = confirmed;
463
+ this.patch({ dpi: confirmed, dpiStages });
464
+ return confirmed;
465
+ }
466
+ async setLegacyDpi(dpi) {
467
+ const settings = await this.readLegacySettings();
468
+ const stageCount = Math.min(Math.max(settings.data[11] ?? 1, 1), 4);
469
+ const stage = Math.min(settings.data[20] ?? 0, stageCount - 1);
470
+ const stages = Array.from({ length: 4 }, (_, index) => {
471
+ const offset = 12 + index * 2;
472
+ return ninjutsoLegacyDecodeDpi(settings.data[offset], settings.data[offset + 1]);
473
+ });
474
+ stages[stage] = dpi;
475
+ const payload = ninjutsoLegacyRequest(5, settings.profile);
476
+ payload[8] = stageCount;
477
+ stages
478
+ .flatMap((value, index) => index < stageCount ? ninjutsoLegacyEncodeDpi(value) : [0, 0])
479
+ .forEach((value, index) => payload[9 + index] = value);
480
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(payload));
481
+ const confirmedSettings = await this.readLegacySettings();
482
+ const offset = 12 + stage * 2;
483
+ const confirmed = ninjutsoLegacyDecodeDpi(confirmedSettings.data[offset], confirmedSettings.data[offset + 1]);
484
+ if (confirmed !== dpi)
485
+ throw new Error(`The mouse kept ${confirmed} DPI instead of ${dpi} DPI.`);
486
+ const dpiStages = this.lastStatus?.dpiStages?.slice();
487
+ if (dpiStages)
488
+ dpiStages[stage] = confirmed;
489
+ this.patch({ dpi: confirmed, dpiStages });
490
+ return confirmed;
491
+ }
492
+ async ensureEffectiveProductId() {
493
+ if (this.effectiveProductId !== null)
494
+ return this.effectiveProductId;
495
+ if (!this.isWireless())
496
+ return this.effectiveProductId = this.device.productId;
497
+ if (this.isLegacy()) {
498
+ const payload = new Uint8Array(NINJUTSO_LEGACY_PAYLOAD_LENGTH);
499
+ payload.set([40, 0, 0, 1, 0, 0, 2]);
500
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(payload));
501
+ await delay(5);
502
+ const response = await this.device.receiveFeatureReport(NINJUTSO_LEGACY_REPORT_ID);
503
+ return this.effectiveProductId = response.getUint8(10) << 8 | response.getUint8(9);
504
+ }
505
+ const response = await this.readCurrent(NINJUTSO_COMMAND.pairedProductId);
506
+ return this.effectiveProductId = response[1] << 8 | response[0];
507
+ }
508
+ async readCurrent(command, args = [], attempts = 4) {
509
+ const profileCommands = new Set([
510
+ NINJUTSO_COMMAND.activeDpiStage,
511
+ NINJUTSO_COMMAND.dpiStageCount,
512
+ NINJUTSO_COMMAND.dpi,
513
+ NINJUTSO_COMMAND.pollingRate,
514
+ NINJUTSO_COMMAND.liftOffDistance,
515
+ NINJUTSO_COMMAND.angleTuning,
516
+ NINJUTSO_COMMAND.motionSync,
517
+ NINJUTSO_COMMAND.systemMode,
518
+ NINJUTSO_COMMAND.hyperClick,
519
+ NINJUTSO_COMMAND.slamClick,
520
+ NINJUTSO_COMMAND.opticalEngine,
521
+ NINJUTSO_COMMAND.sleepMinutes,
522
+ NINJUTSO_COMMAND.lightingMode,
523
+ NINJUTSO_COMMAND.lightingColor,
524
+ NINJUTSO_COMMAND.lightingState,
525
+ NINJUTSO_COMMAND.lightingSpeed,
526
+ NINJUTSO_COMMAND.lightingBrightness,
527
+ ]);
528
+ const request = ninjutsoBuildRequest(command, profileCommands.has(command) ? this.profile : 0, args);
529
+ for (let attempt = 0; attempt < attempts; attempt++) {
530
+ await this.device.sendFeatureReport(NINJUTSO_REPORT_ID, buffer(request));
531
+ await delay(attempt === 0 ? 30 : 60);
532
+ const response = await this.device.receiveFeatureReport(NINJUTSO_REPORT_ID);
533
+ const value = ninjutsoResponseValue(response, command);
534
+ if (value)
535
+ return value;
536
+ }
537
+ throw new NinjutsoCommandTimeoutError(`The Ninjutso mouse did not answer command 0x${command.toString(16)}.`);
538
+ }
539
+ async readCurrentOptional(command, args = []) {
540
+ try {
541
+ // Unsupported commands return a well-formed all-zero report immediately;
542
+ // retrying that response cannot make the capability appear.
543
+ return await this.readCurrent(command, args, 1);
544
+ }
545
+ catch (error) {
546
+ if (error instanceof NinjutsoCommandTimeoutError)
547
+ return null;
548
+ throw error;
549
+ }
550
+ }
551
+ async sendCurrent(command, args) {
552
+ await this.device.sendFeatureReport(NINJUTSO_REPORT_ID, buffer(ninjutsoBuildRequest(command, this.profile, args)));
553
+ }
554
+ async setCurrentOption(label, write, read, enabled, key) {
555
+ return await this.run(async () => {
556
+ await this.open();
557
+ if (this.isLegacy())
558
+ throw new Error(`${label} is not available on Sora V2.`);
559
+ await this.sendCurrent(write, [enabled ? 1 : 0]);
560
+ const confirmed = (await this.readCurrent(read))[0] === 1;
561
+ if (confirmed !== enabled)
562
+ throw new Error(`The mouse left ${label} ${confirmed ? "on" : "off"}.`);
563
+ this.patch({ [key]: confirmed });
564
+ return confirmed;
565
+ });
566
+ }
567
+ async readCurrentLighting(direct) {
568
+ const state = await this.readCurrentOptional(NINJUTSO_COMMAND.lightingState);
569
+ if (!state)
570
+ return null;
571
+ const modeReply = await this.readCurrentOptional(NINJUTSO_COMMAND.lightingMode);
572
+ const speedReply = await this.readCurrentOptional(NINJUTSO_COMMAND.lightingSpeed);
573
+ const colorReply = await this.readCurrentOptional(NINJUTSO_COMMAND.lightingColor);
574
+ const brightnessReply = direct ? await this.readCurrentOptional(NINJUTSO_COMMAND.lightingBrightness) : null;
575
+ const modeMap = [null, "Static", "Cycling", "Wave"];
576
+ const selected = state[0] === 0 ? "Off" : modeMap[modeReply?.[0] ?? 0] ?? "Static";
577
+ const effects = direct ? ["Off", "Static", "Wave"] : ["Off", "Static", "Cycling", "Wave"];
578
+ return {
579
+ zone: "Receiver",
580
+ modes: effects,
581
+ mode: selected,
582
+ color: colorReply ? this.rgbToHex(colorReply[0], colorReply[1], colorReply[2]) : null,
583
+ color2: null,
584
+ colorModes: ["Static"],
585
+ dualColorModes: [],
586
+ reactiveModes: ["Cycling", "Wave"],
587
+ speeds: Array.from({ length: 21 }, (_, index) => index),
588
+ speed: speedReply ? 20 - (speedReply[0] ?? 10) : null,
589
+ brightness: brightnessReply ? (brightnessReply[0] ?? 1) * 25 : null,
590
+ brightnessLevels: direct ? [25, 50, 75, 100] : [],
591
+ };
592
+ }
593
+ rgbToHex(red, green, blue) {
594
+ return `#${[red, green, blue].map((value) => value.toString(16).padStart(2, "0")).join("")}`;
595
+ }
596
+ hexToRgb(value) {
597
+ if (!/^#[0-9a-f]{6}$/i.test(value))
598
+ throw new Error("Lighting colour must be a six-digit hex colour.");
599
+ return [1, 3, 5].map((offset) => Number.parseInt(value.slice(offset, offset + 2), 16));
600
+ }
601
+ async setControl(resume) {
602
+ const payload = new Uint8Array(NINJUTSO_CONTROL_PAYLOAD_LENGTH);
603
+ payload.set(resume ? [28, 27, 0, 0, 1] : [27, 26, 0, 0, 1]);
604
+ await this.device.sendFeatureReport(NINJUTSO_CONTROL_REPORT_ID, buffer(payload));
605
+ await delay(30);
606
+ }
607
+ async readLegacySettings() {
608
+ const profileRequest = ninjutsoLegacyRequest(13);
609
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(profileRequest));
610
+ await delay(15);
611
+ let profileReply = await this.device.receiveFeatureReport(NINJUTSO_LEGACY_REPORT_ID);
612
+ if (profileReply.getUint8(9) === 0) {
613
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(profileRequest));
614
+ await delay(15);
615
+ profileReply = await this.device.receiveFeatureReport(NINJUTSO_LEGACY_REPORT_ID);
616
+ }
617
+ const profile = profileReply.getUint8(9);
618
+ const compact = this.device.productName === "Ninjutso Sora V2 8K";
619
+ const payloadLength = compact ? 73 : 703;
620
+ const request = new Uint8Array(payloadLength);
621
+ request.set([38, 0, 0, 1, 0, profile]);
622
+ await this.device.sendFeatureReport(4, buffer(request));
623
+ await delay(90);
624
+ const response = await this.device.receiveFeatureReport(4);
625
+ const bytes = new Uint8Array(response.buffer, response.byteOffset, response.byteLength);
626
+ const sumEnd = compact ? 71 : 701;
627
+ const checksumOffset = compact ? 72 : 702;
628
+ const sum = bytes.slice(0, sumEnd).reduce((total, value) => total + value, 0);
629
+ const expected = ((bytes[checksumOffset + 1] ?? 0) << 8) | (bytes[checksumOffset] ?? 0);
630
+ if (sum !== expected)
631
+ throw new Error("The Sora V2 settings checksum did not match.");
632
+ return { profile, data: bytes.slice(9) };
633
+ }
634
+ async readLegacyFirmware() {
635
+ const read = async (selector) => {
636
+ const request = ninjutsoLegacyRequest(9);
637
+ request[6] = selector;
638
+ await this.device.sendFeatureReport(NINJUTSO_LEGACY_REPORT_ID, buffer(request));
639
+ await delay(15);
640
+ const response = await this.device.receiveFeatureReport(NINJUTSO_LEGACY_REPORT_ID);
641
+ return [12, 11, 10, 9].map((offset) => response.getUint8(offset).toString(16).padStart(2, "0")).join("").toUpperCase();
642
+ };
643
+ const versions = [`Mouse ${await read(this.isWireless() ? 0 : 4)}`];
644
+ if (this.isWireless())
645
+ versions.push(`Receiver ${await read(4)}`);
646
+ return versions;
647
+ }
648
+ decodeFirmware(bytes) {
649
+ return [...bytes.slice(0, 3)].reverse().map((value) => value.toString(16).padStart(2, "0")).join("").toUpperCase();
650
+ }
651
+ legacyRate(code) {
652
+ return [1000, 2000, 4000, 8000][code] ?? 1000;
653
+ }
654
+ decodeLod(code) {
655
+ return LOD_VALUES[code] ?? "Medium";
656
+ }
657
+ signedByte(value) {
658
+ return value >= 0x80 ? value - 0x100 : value;
659
+ }
660
+ patch(changes) {
661
+ if (this.lastStatus)
662
+ this.lastStatus = { ...this.lastStatus, ...changes };
663
+ }
664
+ async run(task) {
665
+ const started = this.queue.then(task, task);
666
+ this.queue = started.catch(() => undefined);
667
+ return await started;
668
+ }
669
+ }
670
+ function hasFeatureReport(collections, reportId) {
671
+ return collections.some((collection) => collection.featureReports.some((report) => report.reportId === reportId)
672
+ || hasFeatureReport(collection.children, reportId));
673
+ }
674
+ function delay(milliseconds) {
675
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
676
+ }
677
+ function buffer(payload) {
678
+ return new Uint8Array(payload).buffer;
679
+ }
680
+ //# sourceMappingURL=hid.js.map