@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,728 @@
1
+ import { VENDOR_ID } from "../vendors.js";
2
+ import { LAMZU_PRODUCTS } from "@openmouse/protocol/lamzu";
3
+ import { buildX11DpiReport, decodeX11DpiReport, nearestX11Dpi, X11_DPI_DEFAULT_ACTIVE, X11_DPI_DEFAULT_STAGES, X11_DPI_MAX, X11_DPI_MIN, X11_DPI_REPORT_ID, X11_DPI_STAGE_COUNT, X11_DPI_STEP, } from "./dpi.js";
4
+ // Attack Shark mice ship from multiple OEMs with different VIDs and protocols:
5
+ //
6
+ // 0x1d57 — R1, X11 family: HID feature reports, 250 ms cmd delay
7
+ // 0x25a7 — X3, X6, X8, X11 direct: GearHub-derived protocol (report 0, 64 B)
8
+ // 0x373e — R5 Ultra, R3 (Lamzu OEM) — usagePage 0xffff feature reports
9
+ //
10
+ // PIDs change between firmware revisions, so detection is collection-based,
11
+ // not PID-based. For 0x373e we exclude known Lamzu PIDs.
12
+ //
13
+ // Real X11 hardware (0x1d57, wired 0xfa55 and wireless 0xfa60) exposes NO
14
+ // feature reports to the browser on any of its four HID entries. Its config
15
+ // channel is USB interface 2 (a system-control/consumer composite; see the
16
+ // lsusb dump in dressedinblack5/attack-shark-x11-electron docs/descritors),
17
+ // and WebHID only surfaces the Consumer collection, which declares none. The
18
+ // config feature reports (0x06 polling, 0x04 DPI) are still reachable through
19
+ // the OS HID stack on interface 2's `&col04` sub-collection: node-hid does
20
+ // this on Windows with the stock input.inf (no Zadig/WinUSB), and the Tauri
21
+ // Desktop app's Rust hidapi adapter opens every sub-collection path too. The
22
+ // browser-side collection gate below therefore refuses these units, and the
23
+ // X11-family helper turns that refusal into a real explanation; the
24
+ // collections-less native branch writes the same packets over such an adapter.
25
+ //
26
+ // Protocol source: xb-bx/attack-shark-r1-driver (Odin)
27
+ // HarukaYamamoto0/attack-shark-x11-driver (TypeScript)
28
+ // qmk.top GearHub bundle (MU class — 0x25a7 protocol)
29
+ // Research credit: viix0dev
30
+ // ── VID constants ─────────────────────────────────────────────────────────
31
+ const VID_1D57 = 0x1d57; // R1 / X11 family
32
+ const VID_25A7 = VENDOR_ID.attackShark; // X3, X6, X8, X11 direct
33
+ const VID_373E = 0x373e; // Lamzu OEM (R5 Ultra, R3)
34
+ // ── 0x1d57 protocol (R1 / X11) ───────────────────────────────────────────
35
+ // Confirmed from open-source driver research.
36
+ const CMD_DELAY_MS = 300;
37
+ // Polling rate: feature report 0x06, 9 bytes.
38
+ // [len=0x09, 0x01, rate_byte, checksum, 0, 0, 0, 0]
39
+ // (The browser prepends the report ID 0x06 when calling sendFeatureReport.)
40
+ const POLLING_REPORT_ID = 0x06;
41
+ const POLLING_RATES_1D57 = [
42
+ [0x08, 125],
43
+ [0x04, 250],
44
+ [0x02, 500],
45
+ [0x01, 1000],
46
+ ];
47
+ const DPI_READ_REPORT_ID = 0xa0;
48
+ // Battery arrives as input report with this 4-byte signature; byte 4 = %.
49
+ // The leading 0x03 is the HID report id of the battery packet.
50
+ const BATTERY_SIGNATURE = [0x03, 0x55, 0x40, 0x01];
51
+ const BATTERY_REPORT_ID = BATTERY_SIGNATURE[0];
52
+ // ── 0x25a7 protocol (GearHub / MU class) ─────────────────────────────────
53
+ // Reverse-engineered from the qmk.top GearHub web driver JS bundle.
54
+ // Uses HID feature reports on report ID 0x00, 64 bytes total.
55
+ // Commands are padded to 9 bytes; checksum goes in byte[7].
56
+ const REPORT_ID_25A7 = 0x00;
57
+ const REPORT_LEN_25A7 = 64;
58
+ const CMD_LEN_25A7 = 9;
59
+ const CMD_DELAY_25A7_MS = 100;
60
+ // Command IDs (MU class)
61
+ const FEA_CMD_GET_REV = 0x80; // Get firmware revision
62
+ const FEA_CMD_GET_DPI = 0xd4; // Get DPI slots (param: profile)
63
+ const FEA_CMD_SET_REPORT_RATE = 0x04; // Set polling rate
64
+ /** Polling-rate byte codes used by the 0x25a7 protocol. */
65
+ export const POLLING_CODES_25A7 = new Map([
66
+ [125, 0x08],
67
+ [250, 0x04],
68
+ [500, 0x02],
69
+ [1000, 0x01],
70
+ [2000, 0x84],
71
+ [4000, 0x82],
72
+ [8000, 0x81],
73
+ ]);
74
+ // ── Collection helpers ─────────────────────────────────────────────────────
75
+ function hasFeatureReports(collection) {
76
+ if (collection.featureReports.length > 0)
77
+ return true;
78
+ return collection.children.some(hasFeatureReports);
79
+ }
80
+ function hasVendorControl(collection) {
81
+ if (collection.usagePage === 0xffff && collection.featureReports.length > 0)
82
+ return true;
83
+ return collection.children.some(hasVendorControl);
84
+ }
85
+ function declaresInputReport(collection, reportId) {
86
+ if (collection.inputReports.some((report) => report.reportId === reportId))
87
+ return true;
88
+ return collection.children.some((child) => declaresInputReport(child, reportId));
89
+ }
90
+ // ── X11 family (config is native-only; battery is readable) ──────────────
91
+ // Documented 0x1d57 PIDs: wired X11, wireless X11 receiver, R1.
92
+ const X11_FAMILY_PIDS = new Set([0xfa55, 0xfa60, 0xfa61]);
93
+ const X11_FAMILY_NAMES = new Map([
94
+ [0xfa55, "Attack Shark X11 (wired)"],
95
+ [0xfa60, "Attack Shark X11 (wireless receiver)"],
96
+ [0xfa61, "Attack Shark R1"],
97
+ ]);
98
+ const X11_FAMILY_MODELS = new Map([
99
+ [0xfa55, "Attack Shark X11"],
100
+ [0xfa60, "Attack Shark X11"],
101
+ [0xfa61, "Attack Shark R1"],
102
+ ]);
103
+ // The wireless receiver's interface 2 pushes battery packets on its own —
104
+ // no command needed — so a read-only claim of that entry costs nothing and
105
+ // risks nothing. The wired PIDs never report battery on this endpoint.
106
+ const X11_WIRELESS_PID = 0xfa60;
107
+ // The X11 family's DPI report 0x04 is documented for the X11 (wired 0xfa55,
108
+ // wireless 0xfa60). The R1 (0xfa61) uses a different DpiBuilder/step map in
109
+ // the reference driver, so it stays out of this path until ported.
110
+ const X11_DPI_PIDS = new Set([0xfa55, 0xfa60]);
111
+ const x11DpiStates = new Map();
112
+ function x11DpiStateFor(productId) {
113
+ let state = x11DpiStates.get(productId);
114
+ if (!state) {
115
+ state = {
116
+ stages: [...X11_DPI_DEFAULT_STAGES],
117
+ activeStage: X11_DPI_DEFAULT_ACTIVE,
118
+ angleSnap: false,
119
+ rippleControl: true,
120
+ };
121
+ x11DpiStates.set(productId, state);
122
+ }
123
+ return state;
124
+ }
125
+ /** Test/diagnostic hook: forget cached X11 DPI state (defaults come back). */
126
+ export function resetAttackSharkX11DpiState() {
127
+ x11DpiStates.clear();
128
+ }
129
+ // Battery and polling rate are both push/last-known rather than readable: the
130
+ // receiver streams `03 55 40 01 <pct>` on interface 2 on its own, and the
131
+ // firmware has no polling-rate read-back. This process keeps the last value it
132
+ // saw per product id so a short-lived client can still report it. The X11's
133
+ // reference driver and the web app's own X11 bridge both default the polling
134
+ // rate to 1,000 Hz for the same reason.
135
+ const X11_DEFAULT_POLLING_HZ = 1000;
136
+ /** How long a battery sample stays fresh enough to skip waiting for another. */
137
+ const X11_BATTERY_TTL_MS = 30_000;
138
+ /** Longest a status read waits for the receiver's next battery packet. */
139
+ const X11_BATTERY_WAIT_MS = 2_500;
140
+ const x11RuntimeStates = new Map();
141
+ function x11RuntimeFor(productId) {
142
+ let state = x11RuntimeStates.get(productId);
143
+ if (!state) {
144
+ state = { pollingRateHz: X11_DEFAULT_POLLING_HZ, batteryPercent: null, batteryAt: 0 };
145
+ x11RuntimeStates.set(productId, state);
146
+ }
147
+ return state;
148
+ }
149
+ /** Test/diagnostic hook: forget cached X11 battery/polling state. */
150
+ export function resetAttackSharkX11RuntimeState() {
151
+ x11RuntimeStates.clear();
152
+ }
153
+ /**
154
+ * If the granted devices include an X11-family unit that no driver could
155
+ * claim, explain why instead of letting the generic "not a control
156
+ * interface" error blame the picker choice. This fires only when the
157
+ * status entry (the composite with a Consumer collection) was not among
158
+ * the grants — the rows look identical in the picker, so say how to get
159
+ * the right one — and it stays honest about settings being native-only.
160
+ * Returns null when no X11-family device is present.
161
+ */
162
+ export function attackSharkNativeOnlyMessage(devices) {
163
+ const unit = devices.find((device) => device.vendorId === VID_1D57 && X11_FAMILY_PIDS.has(device.productId));
164
+ if (!unit)
165
+ return null;
166
+ const name = X11_FAMILY_NAMES.get(unit.productId) ?? "Attack Shark X11";
167
+ return `This ${name} cannot be configured through the browser: its settings channel `
168
+ + "is on an interface the browser is not allowed to reach. To change DPI, polling "
169
+ + "rate and lighting, install the OpenMouse Bridge, then open Interface settings "
170
+ + "→ Bridge → Native devices and click “Enable native control”.";
171
+ }
172
+ function detectFamily(device) {
173
+ if (device.vendorId === VID_1D57) {
174
+ // Native HID adapters (Tauri's TauriHidDevice, the Node/Bridge adapter)
175
+ // cannot parse the report descriptor and report no collections at all,
176
+ // so every collection-based gate below would refuse these units. On that
177
+ // transport the vendor feature reports are reachable, so identify the
178
+ // family from the vendor/product id instead. WebHID always reports the
179
+ // real collection tree, so this branch never fires in a browser.
180
+ if (device.collections.length === 0) {
181
+ return X11_FAMILY_PIDS.has(device.productId) ? "1d57-x11" : null;
182
+ }
183
+ // Some 0x1d57 mice (X8 SE, X11) use the GearHub protocol despite
184
+ // sharing the R1 VID. Distinguish by checking for a vendor-specific
185
+ // collection (usagePage 0xffff) which the GearHub interface exposes.
186
+ if (device.collections.some(hasVendorControl))
187
+ return "25a7";
188
+ if (device.collections.some(hasFeatureReports))
189
+ return "1d57";
190
+ // Real X11/R1 units declare no feature reports anywhere (see header
191
+ // note), so config writes are impossible here — but their interface-2
192
+ // entry, the composite with a Consumer top-level collection, carries the
193
+ // autonomous battery stream. Claim that one read-only; the plain boot
194
+ // keyboard/mouse entries stay refused.
195
+ if (X11_FAMILY_PIDS.has(device.productId)
196
+ && device.collections.some((collection) => collection.usagePage === 0x0c)) {
197
+ return "1d57-x11";
198
+ }
199
+ return null;
200
+ }
201
+ if (device.vendorId === VID_25A7) {
202
+ // Same native-adapter reasoning as VID_1D57 above: with no report
203
+ // descriptor to inspect, the vendor id alone identifies the GearHub
204
+ // family.
205
+ if (device.collections.length === 0)
206
+ return "25a7";
207
+ return device.collections.some(hasVendorControl) ? "25a7" : null;
208
+ }
209
+ if (device.vendorId === VID_373E) {
210
+ if (LAMZU_PRODUCTS.has(device.productId))
211
+ return null;
212
+ return device.collections.some(hasVendorControl) ? "373e" : null;
213
+ }
214
+ return null;
215
+ }
216
+ // ── 0x25a7 helpers ────────────────────────────────────────────────────────
217
+ /**
218
+ * Compute the GearHub checksum: one's-complement of the sum of the first 7
219
+ * command bytes, stored in byte 7. Byte 8 stays zero (unused padding).
220
+ */
221
+ export function checksum25a7(cmd) {
222
+ const out = new Uint8Array(CMD_LEN_25A7);
223
+ out.set(cmd.subarray(0, Math.min(cmd.length, CMD_LEN_25A7)));
224
+ let sum = 0;
225
+ for (let i = 0; i < 7; i++)
226
+ sum = (sum + out[i]) & 0xff;
227
+ out[7] = (0xff - sum) & 0xff;
228
+ return out;
229
+ }
230
+ /**
231
+ * Encode a 64-byte HID report that starts with the 9-byte padded+checksummed
232
+ * command and is zero-padded to REPORT_LEN_25A7.
233
+ */
234
+ function encodeReport25a7(cmd) {
235
+ const report = new Uint8Array(REPORT_LEN_25A7);
236
+ report.set(checksum25a7(cmd));
237
+ return report;
238
+ }
239
+ /** Lookup a polling-rate Hz value and return its byte code. */
240
+ function pollingHzToCode25a7(hz) {
241
+ return POLLING_CODES_25A7.get(hz);
242
+ }
243
+ // ── Driver ────────────────────────────────────────────────────────────────
244
+ export class AttackSharkHidClient {
245
+ device;
246
+ family;
247
+ batteryWaitMs;
248
+ lastStatus = null;
249
+ queue = Promise.resolve();
250
+ batteryPercent = null;
251
+ listening = false;
252
+ constructor(device, options = {}) {
253
+ this.device = device;
254
+ this.family = detectFamily(device);
255
+ this.batteryWaitMs = options.batteryWaitMs ?? X11_BATTERY_WAIT_MS;
256
+ }
257
+ /**
258
+ * True when this client is running over a native HID adapter (Tauri's
259
+ * TauriHidDevice, the Node/Bridge adapter) rather than WebHID. Those
260
+ * adapters report no collections, but unlike the browser they can reach
261
+ * the vendor feature reports, so the X11 config channel is writable
262
+ * through them.
263
+ */
264
+ get nativeConfig() {
265
+ return this.device.collections.length === 0;
266
+ }
267
+ /** True when this unit's DPI report 0x04 can be driven over the native channel. */
268
+ get x11DpiSupported() {
269
+ return this.family === "1d57-x11"
270
+ && this.nativeConfig
271
+ && X11_DPI_PIDS.has(this.device.productId);
272
+ }
273
+ static isSupported(device) {
274
+ return detectFamily(device) !== null;
275
+ }
276
+ // Battery packets arrive as inputreport events; the raw packet's leading
277
+ // 0x03 is the HID report id, which WebHID strips into event.reportId, so
278
+ // rebuild the native shape before matching the signature.
279
+ onInputReport = (event) => {
280
+ const data = new Uint8Array(event.data.buffer, event.data.byteOffset, event.data.byteLength);
281
+ const packet = new Uint8Array(data.length + 1);
282
+ packet[0] = event.reportId;
283
+ packet.set(data, 1);
284
+ const percent = AttackSharkHidClient.parseBatteryReport(packet);
285
+ if (percent !== null) {
286
+ this.batteryPercent = percent;
287
+ const runtime = x11RuntimeFor(this.device.productId);
288
+ runtime.batteryPercent = percent;
289
+ runtime.batteryAt = Date.now();
290
+ if (this.lastStatus) {
291
+ this.lastStatus = { ...this.lastStatus, batteryPercent: percent, batteryState: "Discharging" };
292
+ }
293
+ }
294
+ };
295
+ async open() {
296
+ if (!this.device.opened)
297
+ await this.device.open();
298
+ if (this.family === "1d57-x11" && !this.listening) {
299
+ this.device.addEventListener("inputreport", this.onInputReport);
300
+ this.listening = true;
301
+ }
302
+ }
303
+ async close() {
304
+ this.lastStatus = null;
305
+ if (this.listening) {
306
+ this.device.removeEventListener("inputreport", this.onInputReport);
307
+ this.listening = false;
308
+ }
309
+ if (this.device.opened)
310
+ await this.device.close();
311
+ }
312
+ async startNotifications() {
313
+ return false;
314
+ }
315
+ displayName() {
316
+ // X11-family product strings are generic OEM labels ("2.4G Wireless
317
+ // Device", "USB Gaming Mouse"), so name those models by PID instead.
318
+ const model = this.device.vendorId === VID_1D57
319
+ ? X11_FAMILY_MODELS.get(this.device.productId)
320
+ : undefined;
321
+ if (model)
322
+ return model;
323
+ const name = this.device.productName?.trim();
324
+ if (!name)
325
+ return "Attack Shark";
326
+ return /^attack\s*shark/i.test(name) ? name : `Attack Shark ${name}`;
327
+ }
328
+ deviceBrand() {
329
+ return "Attack Shark";
330
+ }
331
+ isWireless() {
332
+ if (this.device.vendorId === VID_1D57 && X11_FAMILY_PIDS.has(this.device.productId)) {
333
+ return this.device.productId === X11_WIRELESS_PID;
334
+ }
335
+ return /receiver|dongle|wireless|2\.4g/i.test(this.device.productName || "");
336
+ }
337
+ getSupportedPollingRates() {
338
+ if (this.family === "1d57")
339
+ return POLLING_RATES_1D57.map(([, hz]) => hz);
340
+ if (this.family === "25a7")
341
+ return [...POLLING_CODES_25A7.keys()];
342
+ // Native transport: the X11 exposes the same 0x06 polling command the
343
+ // browser cannot reach, so advertise the rates it accepts.
344
+ if (this.family === "1d57-x11" && this.nativeConfig)
345
+ return POLLING_RATES_1D57.map(([, hz]) => hz);
346
+ return [];
347
+ }
348
+ getDpiOptions() {
349
+ // 25a7 devices expose up to 8 DPI slots per profile.
350
+ // The actual values are read dynamically in readStatus(); we return a
351
+ // standard set of supported DPI steps so the UI can offer them.
352
+ if (this.family === "25a7") {
353
+ return [400, 800, 1200, 1600, 2400, 3200, 6400, 12000, 26000];
354
+ }
355
+ return [];
356
+ }
357
+ async readStatus() {
358
+ await this.open();
359
+ let pollingRateHz = 0;
360
+ let dpi = 0;
361
+ let firmware = [];
362
+ if (this.family === "1d57") {
363
+ pollingRateHz = await this.read1d57PollingRate().catch(() => 0);
364
+ }
365
+ if (this.family === "25a7") {
366
+ const result = await this.read25a7Status().catch(() => null);
367
+ if (result) {
368
+ pollingRateHz = result.pollingRateHz;
369
+ dpi = result.dpi;
370
+ firmware = result.firmware;
371
+ }
372
+ }
373
+ const dpiState = this.x11DpiSupported ? x11DpiStateFor(this.device.productId) : null;
374
+ if (dpiState) {
375
+ await this.readX11DpiState();
376
+ dpi = dpiState.stages[dpiState.activeStage - 1] ?? 0;
377
+ }
378
+ // Native X11: polling rate has no read-back (report the last value this
379
+ // process applied, defaulting to 1,000 Hz), and the wireless receiver
380
+ // pushes battery on its own — give it a bounded moment to arrive.
381
+ const x11Runtime = this.family === "1d57-x11" && this.nativeConfig
382
+ ? x11RuntimeFor(this.device.productId)
383
+ : null;
384
+ if (x11Runtime) {
385
+ if (this.isWireless())
386
+ await this.waitForX11Battery(x11Runtime);
387
+ pollingRateHz = x11Runtime.pollingRateHz;
388
+ }
389
+ const batteryPercent = x11Runtime ? x11Runtime.batteryPercent : this.batteryPercent;
390
+ return this.lastStatus = {
391
+ brand: "Attack Shark",
392
+ name: this.displayName(),
393
+ ui: {
394
+ family: "attackshark",
395
+ settingsReady: this.family === "1d57"
396
+ || this.family === "25a7"
397
+ || (this.family === "1d57-x11" && this.nativeConfig),
398
+ hideUnsupportedPollingRates: true,
399
+ hideProcessingCard: true,
400
+ // Wireless X11-family units push battery on their own. WebHID only
401
+ // shows the column when the browser can see the battery input report
402
+ // (usually hidden under the protected system-control collection); a
403
+ // native adapter delivers the stream directly, so it is always worth
404
+ // showing there.
405
+ forceShowBattery: this.family === "1d57-x11"
406
+ && this.isWireless()
407
+ && (this.nativeConfig
408
+ || this.device.collections.some((collection) => declaresInputReport(collection, BATTERY_REPORT_ID))),
409
+ statusNote: this.family === "1d57-x11" && !this.nativeConfig
410
+ ? "Status only: this mouse's settings channel is not reachable from a browser and needs a native driver."
411
+ : undefined,
412
+ ...(dpiState
413
+ ? {
414
+ dpiStageEditor: {
415
+ maxStages: X11_DPI_STAGE_COUNT,
416
+ countEditable: false,
417
+ minDpi: X11_DPI_MIN,
418
+ maxDpi: X11_DPI_MAX,
419
+ stepDpi: X11_DPI_STEP,
420
+ },
421
+ }
422
+ : {}),
423
+ },
424
+ batteryPercent,
425
+ batteryState: batteryPercent !== null ? "Discharging" : "Unknown",
426
+ dpi,
427
+ ...(dpiState
428
+ ? {
429
+ dpiStages: [...dpiState.stages],
430
+ activeDpiStage: dpiState.activeStage - 1,
431
+ angleSnapping: dpiState.angleSnap,
432
+ rippleControl: dpiState.rippleControl,
433
+ }
434
+ : {}),
435
+ pollingRateHz,
436
+ supportedPollingRates: this.getSupportedPollingRates(),
437
+ activeProfile: null,
438
+ connectionType: this.isWireless() ? "Wireless" : "Wired",
439
+ liftOffDistance: null,
440
+ firmware,
441
+ };
442
+ }
443
+ async setPollingRate(pollingRateHz) {
444
+ if (this.family === "1d57-x11") {
445
+ if (!this.nativeConfig) {
446
+ throw new Error("This mouse's settings channel is not reachable from a browser; "
447
+ + "changing settings needs the native Attack Shark X11 driver.");
448
+ }
449
+ // Native transport: the same 0x06 feature report the 0x1d57 (R1) path
450
+ // uses. This firmware exposes no read-back command, so trust the write
451
+ // and cache the value rather than confirming it.
452
+ const entry = POLLING_RATES_1D57.find(([, hz]) => hz === pollingRateHz);
453
+ if (!entry)
454
+ throw new Error(`This mouse does not support ${pollingRateHz} Hz.`);
455
+ await this.write1d57PollingRate(entry[0]);
456
+ x11RuntimeFor(this.device.productId).pollingRateHz = pollingRateHz;
457
+ if (this.lastStatus)
458
+ this.lastStatus = { ...this.lastStatus, pollingRateHz };
459
+ return pollingRateHz;
460
+ }
461
+ if (this.family === "1d57") {
462
+ const entry = POLLING_RATES_1D57.find(([, hz]) => hz === pollingRateHz);
463
+ if (!entry)
464
+ throw new Error(`This mouse does not support ${pollingRateHz} Hz.`);
465
+ await this.write1d57PollingRate(entry[0]);
466
+ const confirmed = await this.read1d57PollingRate();
467
+ if (confirmed !== pollingRateHz) {
468
+ throw new Error(`The mouse kept ${confirmed} Hz instead of ${pollingRateHz} Hz.`);
469
+ }
470
+ if (this.lastStatus)
471
+ this.lastStatus = { ...this.lastStatus, pollingRateHz: confirmed };
472
+ return confirmed;
473
+ }
474
+ if (this.family === "25a7") {
475
+ const code = pollingHzToCode25a7(pollingRateHz);
476
+ if (code === undefined)
477
+ throw new Error(`This mouse does not support ${pollingRateHz} Hz.`);
478
+ await this.write25a7PollingRate(code);
479
+ if (this.lastStatus)
480
+ this.lastStatus = { ...this.lastStatus, pollingRateHz };
481
+ return pollingRateHz;
482
+ }
483
+ throw new Error("Polling rate control is not yet implemented for this Attack Shark model.");
484
+ }
485
+ // ── X11 DPI (report 0x04) ─────────────────────────────────────────────
486
+ /** Throw the same explanation the browser path gives when DPI cannot be driven. */
487
+ requireX11Dpi() {
488
+ if (!this.x11DpiSupported) {
489
+ throw new Error(this.family === "1d57-x11"
490
+ ? "This mouse's settings channel is not reachable from a browser; "
491
+ + "changing DPI needs the native Attack Shark X11 driver."
492
+ : "DPI control is not yet implemented for this Attack Shark model.");
493
+ }
494
+ }
495
+ /**
496
+ * Re-send the full six-stage table. The firmware has no partial update and
497
+ * no reliable read-back, so every edit carries the whole table — the same
498
+ * approach the reference driver takes.
499
+ */
500
+ async writeX11Dpi() {
501
+ const state = x11DpiStateFor(this.device.productId);
502
+ const report = buildX11DpiReport({
503
+ stages: state.stages,
504
+ activeStage: state.activeStage,
505
+ angleSnap: state.angleSnap,
506
+ rippleControl: state.rippleControl,
507
+ wired: this.device.productId === 0xfa55,
508
+ });
509
+ // The buffer's leading byte is the report id; WebHID/Tauri take it
510
+ // separately. Copy so the payload is a plain ArrayBuffer-backed view.
511
+ const payload = new Uint8Array(report.length - 1);
512
+ payload.set(report.subarray(1));
513
+ await this.run(() => this.device.sendFeatureReport(X11_DPI_REPORT_ID, payload));
514
+ await this.delay(CMD_DELAY_MS);
515
+ }
516
+ /**
517
+ * Best-effort read of the live table. The reference driver only documents
518
+ * this for the wireless receiver (a GET on report 0x04); the wired unit
519
+ * returns nothing. A failure leaves the cached table untouched rather than
520
+ * aborting the status read.
521
+ */
522
+ async readX11DpiState() {
523
+ if (this.device.productId === 0xfa55)
524
+ return;
525
+ const state = x11DpiStateFor(this.device.productId);
526
+ try {
527
+ const view = await this.run(() => this.device.receiveFeatureReport(X11_DPI_REPORT_ID));
528
+ const bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
529
+ const decoded = decodeX11DpiReport(bytes);
530
+ if (!decoded)
531
+ return;
532
+ state.stages = [...decoded.stages];
533
+ state.activeStage = decoded.activeStage;
534
+ state.angleSnap = decoded.angleSnap;
535
+ state.rippleControl = decoded.rippleControl;
536
+ }
537
+ catch {
538
+ // No read-back on this firmware/transport; keep the cached table.
539
+ }
540
+ }
541
+ /**
542
+ * The wireless receiver streams battery on its own, so the only way to get
543
+ * a fresh percentage is to stay open for its next packet. Skip the wait when
544
+ * the last sample is still fresh — the desktop app re-reads every few
545
+ * seconds and should not pay this each time.
546
+ */
547
+ async waitForX11Battery(runtime) {
548
+ if (runtime.batteryPercent !== null && Date.now() - runtime.batteryAt < X11_BATTERY_TTL_MS)
549
+ return;
550
+ const start = Date.now();
551
+ const deadline = start + this.batteryWaitMs;
552
+ while (Date.now() < deadline) {
553
+ await this.delay(100);
554
+ if (runtime.batteryPercent !== null && runtime.batteryAt >= start)
555
+ return;
556
+ }
557
+ }
558
+ /** Sets the active stage's DPI, preserving the other five. */
559
+ async setDpi(dpi, _dpiY) {
560
+ this.requireX11Dpi();
561
+ const state = x11DpiStateFor(this.device.productId);
562
+ const value = nearestX11Dpi(dpi);
563
+ state.stages[state.activeStage - 1] = value;
564
+ await this.writeX11Dpi();
565
+ if (this.lastStatus)
566
+ this.lastStatus = { ...this.lastStatus, dpi: value };
567
+ return value;
568
+ }
569
+ /** Edits one stage's DPI. `stage` is 0-based, matching the shared UI contract. */
570
+ async setDpiStageValue(stage, dpi) {
571
+ this.requireX11Dpi();
572
+ if (!Number.isInteger(stage) || stage < 0 || stage >= X11_DPI_STAGE_COUNT) {
573
+ throw new RangeError(`This mouse has no DPI stage ${stage + 1}.`);
574
+ }
575
+ const state = x11DpiStateFor(this.device.productId);
576
+ const value = nearestX11Dpi(dpi);
577
+ state.stages[stage] = value;
578
+ await this.writeX11Dpi();
579
+ if (this.lastStatus)
580
+ this.lastStatus = { ...this.lastStatus, dpiStages: [...state.stages] };
581
+ return value;
582
+ }
583
+ /** Selects the active stage. `stage` is 0-based, matching the shared UI contract. */
584
+ async setActiveDpiStage(stage) {
585
+ this.requireX11Dpi();
586
+ if (!Number.isInteger(stage) || stage < 0 || stage >= X11_DPI_STAGE_COUNT) {
587
+ throw new RangeError(`This mouse has no DPI stage ${stage + 1}.`);
588
+ }
589
+ const state = x11DpiStateFor(this.device.productId);
590
+ state.activeStage = stage + 1;
591
+ await this.writeX11Dpi();
592
+ if (this.lastStatus) {
593
+ this.lastStatus = {
594
+ ...this.lastStatus,
595
+ dpi: state.stages[stage] ?? this.lastStatus.dpi,
596
+ activeDpiStage: stage,
597
+ };
598
+ }
599
+ return stage;
600
+ }
601
+ async setAngleSnapping(enabled) {
602
+ this.requireX11Dpi();
603
+ x11DpiStateFor(this.device.productId).angleSnap = enabled;
604
+ await this.writeX11Dpi();
605
+ if (this.lastStatus)
606
+ this.lastStatus = { ...this.lastStatus, angleSnapping: enabled };
607
+ return enabled;
608
+ }
609
+ async setRippleControl(enabled) {
610
+ this.requireX11Dpi();
611
+ x11DpiStateFor(this.device.productId).rippleControl = enabled;
612
+ await this.writeX11Dpi();
613
+ if (this.lastStatus)
614
+ this.lastStatus = { ...this.lastStatus, rippleControl: enabled };
615
+ return enabled;
616
+ }
617
+ // ── 0x25a7 low-level ──────────────────────────────────────────────────
618
+ /**
619
+ * Send a 9-byte command via a 64-byte HID feature report (report ID 0x00),
620
+ * then wait a short delay for the device to process it.
621
+ */
622
+ async sendCmd25a7(cmd) {
623
+ const report = encodeReport25a7(cmd);
624
+ await this.run(() => this.device.sendFeatureReport(REPORT_ID_25A7, report));
625
+ await this.delay(CMD_DELAY_25A7_MS);
626
+ }
627
+ /**
628
+ * Send a command and read back the 64-byte feature report reply.
629
+ */
630
+ async askCmd25a7(cmd) {
631
+ await this.sendCmd25a7(cmd);
632
+ const reply = await this.run(() => this.device.receiveFeatureReport(REPORT_ID_25A7));
633
+ return this.copyView(reply);
634
+ }
635
+ /**
636
+ * Get firmware revision string(s) from the device.
637
+ * Command 0x80 → response byte[1..2] = version (little-endian uint16).
638
+ */
639
+ async getFirmware25a7() {
640
+ const resp = await this.askCmd25a7(new Uint8Array([FEA_CMD_GET_REV]));
641
+ if (resp[0] !== FEA_CMD_GET_REV)
642
+ return [];
643
+ const version = resp[1] | (resp[2] << 8);
644
+ return version !== 0 ? [`v${version}`] : [];
645
+ }
646
+ /**
647
+ * Get DPI configuration for a profile.
648
+ * Command 0xD4 [profile] → response contains active DPI index, slot count,
649
+ * and per-slot X/Y values encoded as LE uint16.
650
+ */
651
+ async getDpi25a7(profile) {
652
+ const resp = await this.askCmd25a7(new Uint8Array([FEA_CMD_GET_DPI, profile]));
653
+ if (resp[0] !== FEA_CMD_GET_DPI)
654
+ return { activeIndex: 0, slots: 0, dpis: [] };
655
+ const activeIndex = resp[2] > 8 ? 0 : resp[2];
656
+ const slotCount = resp[3];
657
+ const dpis = [];
658
+ for (let i = 0; i < slotCount; i++) {
659
+ const x = resp[8 + i * 2] | (resp[9 + i * 2] << 8);
660
+ dpis.push(x);
661
+ }
662
+ return { activeIndex, slots: slotCount, dpis };
663
+ }
664
+ /**
665
+ * Set polling rate via command 0x04.
666
+ */
667
+ async write25a7PollingRate(code) {
668
+ await this.sendCmd25a7(new Uint8Array([FEA_CMD_SET_REPORT_RATE, 0, code]));
669
+ }
670
+ /**
671
+ * Read all status from a 0x25a7 device (firmware + DPI + polling rate).
672
+ */
673
+ async read25a7Status() {
674
+ const firmware = await this.getFirmware25a7();
675
+ // Read DPI from profile 0
676
+ const dpiResult = await this.getDpi25a7(0);
677
+ const dpi = dpiResult.dpis[dpiResult.activeIndex] ?? 0;
678
+ // Polling rate is not directly readable via a single command in the MU
679
+ // class protocol; we default to 1000 Hz and let the user set it.
680
+ const pollingRateHz = 1000;
681
+ return { pollingRateHz, dpi, firmware };
682
+ }
683
+ // ── 0x1d57 low-level ──────────────────────────────────────────────────
684
+ async write1d57PollingRate(rateByte) {
685
+ await this.open();
686
+ // 8 data bytes — browser prepends report ID 0x06.
687
+ // Structure: [0x09, 0x01, rate, checksum, 0, 0, 0, 0]
688
+ const data = new Uint8Array([0x09, 0x01, rateByte, (0xff - rateByte) & 0xff, 0, 0, 0, 0]);
689
+ await this.run(() => this.device.sendFeatureReport(POLLING_REPORT_ID, data));
690
+ await this.delay(CMD_DELAY_MS);
691
+ }
692
+ async read1d57PollingRate() {
693
+ await this.open();
694
+ // Send read-request on report 0xa0 then read back from 0x06.
695
+ const req = new Uint8Array([POLLING_REPORT_ID, 0x00, 0x01, 0, 0, 0, 0, 0]);
696
+ await this.run(() => this.device.sendFeatureReport(DPI_READ_REPORT_ID, req));
697
+ await this.delay(CMD_DELAY_MS);
698
+ const reply = await this.run(() => this.device.receiveFeatureReport(POLLING_REPORT_ID));
699
+ const data = this.copyView(reply);
700
+ const rateByte = data[2]; // byte 2 of feature report (after report ID byte 0)
701
+ const match = POLLING_RATES_1D57.find(([code]) => code === rateByte);
702
+ return match ? match[1] : 0;
703
+ }
704
+ // ── shared helpers ────────────────────────────────────────────────────
705
+ run(task) {
706
+ const next = this.queue.then(task, task);
707
+ this.queue = next.catch(() => undefined);
708
+ return next;
709
+ }
710
+ delay(ms) {
711
+ return new Promise((resolve) => setTimeout(resolve, ms));
712
+ }
713
+ copyView(view) {
714
+ return new Uint8Array(view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength));
715
+ }
716
+ /** Check if an input report matches the battery signature. */
717
+ static isBatteryReport(data) {
718
+ return BATTERY_SIGNATURE.every((byte, i) => data[i] === byte);
719
+ }
720
+ /** Extract battery percentage from a battery input report. */
721
+ static parseBatteryReport(data) {
722
+ if (!AttackSharkHidClient.isBatteryReport(data))
723
+ return null;
724
+ const pct = data[4];
725
+ return pct >= 0 && pct <= 100 ? pct : null;
726
+ }
727
+ }
728
+ //# sourceMappingURL=hid.js.map