1 module razer.hardware;
2 
3 import std.format;
4 import std.string;
5 
6 ///
7 interface RazerDevice {
8   pure {
9     ///
10     string eventFileRegex();
11     
12     /// Vendor id
13     uint usbVid();
14 
15     /// Product id
16     uint usbPid();
17 
18     /// 
19     bool hasMatrix();
20 
21     ///
22     byte height();
23 
24     ///
25     byte width();
26     
27     ///
28     string topUrl();
29 
30     ///
31     string sideImg();
32 
33     ///
34     string perspectiveImg();
35   }
36 }
37 
38 mixin template RazerDeviceFields(
39     string _eventFileRegex,
40     uint _usbPid,
41     byte _height,
42     byte _width,
43     string _topUrl,
44     string _sideImg,
45     string _perspectiveImg
46 ) {
47   pure {
48     ///
49     string eventFileRegex() {
50       return _eventFileRegex;
51     }
52     
53     /// Vendor id
54     uint usbVid() {
55       return 0x1532;
56     }
57 
58     /// Product id
59     uint usbPid() {
60       return _usbPid;
61     }
62 
63     /// 
64     bool hasMatrix() {
65       static if(_width == 0 || _height == 0) {
66         return false;
67       } else {
68         return true;
69       }
70     }
71 
72     ///
73     byte height() {
74       return _height;
75     }
76 
77     ///
78     byte width() {
79       return _width;
80     }
81 
82     ///
83     string topUrl() {
84       return _topUrl;
85     }
86 
87     ///
88     string sideImg() {
89       return _sideImg;
90     }
91 
92     ///
93     string perspectiveImg() {
94       return _perspectiveImg;
95     }
96   }
97 }
98 
99 ///
100 class RazerNostromo : RazerDevice {
101   mixin RazerDeviceFields!(".*Razer_Nostromo-event-kbd",
102   0x0111,
103   0,0,
104   "https://assets.razerzone.com/eeimages/products/59/razer-nostromo-gallery-1.png",
105   "https://assets.razerzone.com/eeimages/products/59/razer-nostromo-gallery-1.png",
106   "https://assets.razerzone.com/eeimages/products/59/razer-nostromo-gallery-2.png");
107 }
108 
109 ///
110 class RazerTartarus : RazerDevice {
111   mixin RazerDeviceFields!(".*Razer_Tartarus(-if01)?-event-kbd",
112   0x0201,
113   0,0,
114   "https://assets2.razerzone.com/images/tartarus-classic/b0535b8924b38f53cb8b853d536798ed-Tartarus-Classic-Base_gallery04.jpg",
115   "https://assets2.razerzone.com/images/tartarus-classic/f89a70c59f993f08e95a8060ee2623da-Tartarus-Classic-Base_gallery02.jpg",
116   "https://assets2.razerzone.com/images/tartarus-classic/b3a11ddda103b2473c3253a0a82af389-Tartarus-Classic-Base_gallery03.jpg");
117 }
118 
119 ///
120 class RazerTartarusChroma : RazerDevice {
121   mixin RazerDeviceFields!(".*Razer_Tartarus_Chroma(-if01)?-event-kbd",
122   0x0208,
123   0,0,
124   "https://assets.razerzone.com/eeimages/products/22356/razer-tartarus-chroma-01-02.png",
125   "https://assets.razerzone.com/eeimages/products/22356/razer-tartarus-chroma-02.png",
126   "https://assets.razerzone.com/eeimages/products/22356/razer-tartarus-chroma-03.png");
127 }
128 
129 ///
130 class RazerOrbweaver : RazerDevice {
131   mixin RazerDeviceFields!(".*Razer_Orbweaver(-if01)?-event-kbd",
132   0x0113,
133   0,0,
134   "https://assets.razerzone.com/eeimages/products/7305/razer-orbweaver-latest-04.png",
135   "https://assets.razerzone.com/eeimages/products/7305/razer-orbweaver-latest-02.png",
136   "https://assets.razerzone.com/eeimages/products/7305/razer-orbweaver-latest-03.png");
137 }
138 
139 
140 ///
141 class RazerOrbweaverChroma : RazerDevice {
142   mixin RazerDeviceFields!(".*Razer_Orbweaver_Chroma(-if01)?-event-kbd",
143   0x0207,
144   0,0,
145   "https://assets2.razerzone.com/images/orbweaver-chroma/370604e681b07ee0ffc2047f569e438e-orbweaver-crhoma-gallery-02.jpg",
146   "https://assets2.razerzone.com/images/orbweaver-chroma/8def7438b6f8d4faf24c9218daa07ad0-orbweaver-crhoma-gallery-03.jpg",
147   "https://assets2.razerzone.com/images/orbweaver-chroma/518c021598fd22a51a714a1b276d1e9e-orbweaver-crhoma-gallery-04.jpg");
148 }
149 
150 ///
151 class RazerBlackWidowUltimate2012 : RazerDevice {
152   mixin RazerDeviceFields!(".*Razer_BlackWidow_Ultimate_2012(-if01)?-event-kbd",
153     0x010D,
154     6, 22,
155     "https://assets.razerzone.com/eeimages/products/22212/razer-blackwidow-ultimate-classic-gallery-4.png",
156     "https://assets.razerzone.com/eeimages/products/22212/razer-blackwidow-ultimate-classic-gallery-1.png",
157     "https://assets.razerzone.com/eeimages/products/22212/razer-blackwidow-ultimate-classic-gallery-2.png");
158 }
159 
160 
161 ///
162 class RazerBlackWidowClassic : RazerDevice {
163   mixin RazerDeviceFields!(".*Razer_BlackWidow(-if01)?-event-kbd",
164     0x011B,
165     6, 22,
166     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-01.png",
167     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-02.png",
168     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-04.png");
169 }
170 
171 ///
172 class RazerBlackWidowClassicAlternate : RazerDevice {
173   mixin RazerDeviceFields!(".*Razer_BlackWidow(-if01)?-event-kbd",
174     0x010E,
175     6, 22,
176     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-01.png",
177     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-02.png",
178     "https://assets.razerzone.com/eeimages/products/17559/razer-blackwidow-gallery-04.png");
179 }
180 
181 ///
182 class RazerBlackWidowUltimate2013 : RazerDevice {
183   mixin RazerDeviceFields!(".*Razer_BlackWidow_Ultimate(_2013)?(-if01)?-event-kbd",
184     0x011A,
185     6, 22,
186     "https://assets.razerzone.com/eeimages/products/17561/razer-blackwidow-ultimate-gallery-02.png",
187     "https://assets.razerzone.com/eeimages/products/17561/razer-blackwidow-ultimate-gallery-01.png",
188     "https://assets.razerzone.com/eeimages/products/17561/razer-blackwidow-ultimate-gallery-04.png");
189 }
190 
191 
192 ///
193 class RazerBlackWidowChroma : RazerDevice {
194   mixin RazerDeviceFields!(".*BlackWidow_Chroma(-if01)?-event-kbd",
195     0x0203,
196     6, 22,
197     "https://assets.razerzone.com/eeimages/products/17557/razer-blackwidow-ultimate-gallery-01.png",
198     "https://assets.razerzone.com/eeimages/products/17557/razer-blackwidow-ultimate-gallery-02.png",
199     "https://assets.razerzone.com/eeimages/products/17557/razer-blackwidow-ultimate-gallery-04.png");
200 }
201 
202 ///
203 class RazerBlackWidowChromaV2 : RazerDevice {
204   ///MATRIX_DIMS = [6, 22]
205 
206   mixin RazerDeviceFields!(".*BlackWidow_Chroma_V2(-if01)?-event-kbd",
207     0x0221,
208     6, 22,
209     "https://assets.razerzone.com/eeimages/products/26600/razer-blackwidow-chroma-v2-gallery-01-wristrest.png",
210     "https://assets.razerzone.com/eeimages/products/26600/razer-blackwidow-chroma-v2-gallery-02-wristrest-green.png",
211     "https://assets.razerzone.com/eeimages/products/26600/razer-blackwidow-chroma-v2-gallery-03-wristrest.png");
212 }
213 
214 ///
215 class RazerBlackWidowChromaTournamentEdition : RazerDevice {
216   ///MATRIX_DIMS = [6, 22]
217 
218   mixin RazerDeviceFields!(".*BlackWidow_Tournament_Edition_Chroma(-if01)?-event-kbd",
219     0x0209,
220     6, 22,
221     "https://assets2.razerzone.com/images/blackwidow-te-chroma/508721b4948304fe823e0d84b2ca114f-Blackwidow-TE-Chroma-Base_gallery2.jpg",
222     "https://assets2.razerzone.com/images/blackwidow-te-chroma/87f7492792c72241c6d5bc302e36d46f-Blackwidow-TE-Chroma-Base_gallery3.jpg",
223     "https://assets2.razerzone.com/images/blackwidow-te-chroma/918fc196cb8aec3e140316650d97a075-Blackwidow-TE-Chroma-Base_gallery5.jpg");
224 }
225 
226 ///
227 class RazerBlackWidowXChroma : RazerDevice {
228   ///MATRIX_DIMS = [6, 22]
229 
230   mixin RazerDeviceFields!(".*BlackWidow_X_Chroma(-if01)?-event-kbd",
231     0x0216,
232     6, 22,
233     "https://assets.razerzone.com/eeimages/products/24325/razer-blackwidow-x-chroma-redo-1.png",
234     "https://assets.razerzone.com/eeimages/products/24325/razer-blackwidow-x-chroma-redo-3.png",
235     "https://assets.razerzone.com/eeimages/products/24325/razer-blackwidow-x-chroma-redo-4.png");
236 }
237 
238 
239 ///
240 class RazerBlackWidowXTournamentEditionChroma : RazerDevice {
241   ///MATRIX_DIMS = [6, 22]
242 
243   mixin RazerDeviceFields!(".*BlackWidow_X_Tournament_Edition_Chroma(-if01)?-event-kbd",
244     0x021a,
245     6, 22,
246     "https://assets.razerzone.com/eeimages/products/24362/razer-blackwidow-te-chroma-gallery-01.png",
247     "https://assets.razerzone.com/eeimages/products/24362/razer-blackwidow-te-chroma-gallery-03.png",
248     "https://assets.razerzone.com/eeimages/products/24362/razer-blackwidow-te-chroma-gallery-04.png");
249 }
250 
251 
252 ///
253 class RazerBladeStealth : RazerDevice {
254   mixin RazerDeviceFields!(".*Razer_Blade_Stealth(-if01)?-event-kbd",
255     0x0205,
256     6, 16,
257     "https://assets.razerzone.com/eeimages/products/23914/razer-blade-stealth-gallery-05-v2.png",
258     "https://assets.razerzone.com/eeimages/products/23914/razer-blade-stealth-gallery-08-v2.png",
259     "https://assets.razerzone.com/eeimages/products/23914/razer-blade-stealth-gallery-01-v2.png");
260 }
261 
262 ///
263 class RazerBladeStealthLate2016 : RazerDevice {
264   ///MATRIX_DIMS = [6, 16]
265 
266   mixin RazerDeviceFields!(".*Razer_Blade_Stealth(-if01)?-event-kbd",
267     0x0220,
268     6, 16,
269     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-15__store_gallery.png",
270     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-22__store_gallery.png",
271     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-02__store_gallery.png");
272 }
273 
274 ///
275 class RazerBladeLate2016 : RazerDevice {
276   mixin RazerDeviceFields!(".*Razer_Blade(-if01)?-event-kbd",
277     0x0224,
278     6, 22,
279     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-07__store_gallery.png",
280     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-13__store_gallery.png",
281     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-01__store_gallery.png");
282 }
283 
284 ///
285 class RazerBladeQHD : RazerDevice {
286   mixin RazerDeviceFields!(".*Razer_Blade(-if01)?-event-kbd",
287     0x020F,
288     6, 16,
289     "https://assets.razerzone.com/eeimages/products/25684/rzrblade14-07__store_gallery.png",
290     "https://assets.razerzone.com/eeimages/products/25684/rzrblade14-13__store_gallery.png",
291     "https://assets.razerzone.com/eeimages/products/25684/rzrblade14-02__store_gallery.png");
292 }
293 
294 ///
295 class RazerBlackWidowXUltimate : RazerDevice {
296   mixin RazerDeviceFields!(".*BlackWidow_Ultimate_2016(-if01)?-event-kbd",
297     0x0217,
298     6, 22,
299     "https://assets.razerzone.com/eeimages/products/24363/razer-blackwidow-x-ultimate-redo-1.png",
300     "https://assets.razerzone.com/eeimages/products/24363/razer-blackwidow-x-ultimate-redo-3.png",
301     "https://assets.razerzone.com/eeimages/products/24363/razer-blackwidow-x-ultimate-redo-4.png");
302 }
303 
304 ///
305 class RazerOrnataChroma : RazerDevice {
306   mixin RazerDeviceFields!(".*Ornata_Chroma(-if01)?-event-kbd",
307     0x021e,
308     6, 22,
309     "https://assets.razerzone.com/eeimages/products/25713/razer-ornata-chroma-gallery-05.png",
310     "https://assets.razerzone.com/eeimages/products/25713/razer-ornata-chroma-gallery-07.png",
311     "https://assets.razerzone.com/eeimages/products/25713/razer-ornata-chroma-gallery-08.png");
312 }
313 
314 ///
315 class RazerOrnata : RazerDevice {
316   mixin RazerDeviceFields!(".*Ornata(-if01)?-event-kbd",
317     0x021f,
318     6, 22,
319     "https://assets.razerzone.com/eeimages/products/25675/razer_ornata_001.png",
320     "https://assets.razerzone.com/eeimages/products/25675/razer_ornata_003.png",
321     "https://assets.razerzone.com/eeimages/products/25675/razer_ornata_004.png");
322 }
323 
324 ///
325 class RazerAnansi : RazerDevice {
326   mixin RazerDeviceFields!(".*Anansi(-if01)?-event-kbd",
327     0x010f,
328     0, 0,
329     "https://assets.razerzone.com/eeimages/products/58/razer-anansi-gallery-5.png",
330     "https://assets.razerzone.com/eeimages/products/58/razer-anansi-gallery-3.png",
331     "https://assets.razerzone.com/eeimages/products/58/razer-anansi-gallery-2.png");
332 }
333 
334 ///
335 class RazerDeathStalkerExpert : RazerDevice {
336   mixin RazerDeviceFields!(".*Razer_DeathStalker(-if01)?-event-kbd",
337     0x0202,
338     0, 0,
339     "https://assets.razerzone.com/eeimages/products/771/razer-dstalk-gallery-5.png",
340     "https://assets.razerzone.com/eeimages/products/771/razer-dstalk-gallery-3.png",
341     "https://assets.razerzone.com/eeimages/products/771/razer-dstalk-gallery-2.png");
342 }
343 
344 ///
345 class RazerDeathStalkerChroma : RazerDevice {
346   ///MATRIX_DIMS = [1, 6]
347 
348   mixin RazerDeviceFields!(".*DeathStalker_Chroma(-if01)?-event-kbd",
349     0x0204,
350     1, 6,
351     "https://assets.razerzone.com/eeimages/products/22563/rzr_deathstalker_chroma_05.png",
352     "https://assets.razerzone.com/eeimages/products/22563/rzr_deathstalker_chroma_03.png",
353     "https://assets.razerzone.com/eeimages/products/22563/rzr_deathstalker_chroma_02.png");
354 }
355 
356 ///
357 class RazerBlackWidowChromaOverwatch : RazerDevice {
358   ///MATRIX_DIMS = [6,22]
359 
360   mixin RazerDeviceFields!(".*BlackWidow_Chroma(-if01)?-event-kbd",
361     0x0211,
362     6, 22,
363     "https://assets.razerzone.com/eeimages/products/23326/overwatch-razer-gallery-5.png",
364     "https://assets.razerzone.com/eeimages/products/23326/overwatch-razer-gallery-3.png",
365     "https://assets.razerzone.com/eeimages/products/23326/overwatch-razer-gallery-1.png");
366 }
367 
368 
369 ///
370 class RazerBladeStealthMid2017 : RazerDevice {
371   mixin RazerDeviceFields!(".*Razer_Blade_Stealth(-if01)?-event-kbd",
372     0x022D,
373     6, 16,
374     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-15__store_gallery.png",
375     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-22__store_gallery.png",
376     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-02__store_gallery.png");
377 }
378 
379 ///
380 class RazerBladePro2017FullHD : RazerDevice {
381   mixin RazerDeviceFields!(".*Razer_Blade_ProFullHD(-if01)?-event-kbd",
382     0x022F,
383     6, 25,
384     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-07__store_gallery.png",
385     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-13__store_gallery.png",
386     "https://assets.razerzone.com/eeimages/products/26227/razer-blade-pro-gallery-01__store_gallery.png");
387 }
388 
389 ///
390 class RazerBladeStealthLate2017 : RazerDevice {
391   mixin RazerDeviceFields!(".*Razer_Blade_Stealth(-if01)?-event-kbd",
392     0x0232,
393     6, 16,
394     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-15__store_gallery.png",
395     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-22__store_gallery.png",
396     "https://assets.razerzone.com/eeimages/products/26727/rzrblade14-02__store_gallery.png");
397 }
398 
399 ///
400 enum RazerDevices = [
401   "RazerNostromo",
402   "RazerTartarus",
403   "RazerTartarusChroma",
404   "RazerOrbweaver",
405   "RazerOrbweaverChroma",
406   "RazerBlackWidowUltimate2012",
407   "RazerBlackWidowClassic",
408   "RazerBlackWidowClassicAlternate",
409   "RazerBlackWidowUltimate2013",
410   "RazerBlackWidowChroma",
411   "RazerBlackWidowChromaV2",
412   "RazerBlackWidowChromaTournamentEdition",
413   "RazerBlackWidowXChroma",
414   "RazerBlackWidowXTournamentEditionChroma",
415   "RazerBladeStealth",
416   "RazerBladeStealthLate2016",
417   "RazerBladeLate2016",
418   "RazerBladeQHD",
419   "RazerBlackWidowXUltimate",
420   "RazerOrnataChroma",
421   "RazerOrnata",
422   "RazerAnansi",
423   "RazerDeathStalkerExpert",
424   "RazerDeathStalkerChroma",
425   "RazerBlackWidowChromaOverwatch",
426   "RazerBladeStealthMid2017",
427   "RazerBladePro2017FullHD",
428   "RazerBladeStealthLate2017" ];
429 
430 RazerDevice getRazerDevice(string name) {
431 
432   static foreach(Device; RazerDevices) {{
433     mixin("auto device = new " ~ Device ~ "();");
434 
435     auto vid = format!"000%X"(device.usbVid)[$-4 .. $];
436     auto pid = format!"000%X"(device.usbPid)[$-4 .. $];
437 
438     string part = vid ~ ":" ~ pid;
439 
440     if(name.indexOf(part) != -1) {
441       return device;
442     }
443   }}
444 
445   assert(false, name ~ " is an unknown device.");
446 }
447 
448 version(unittest) import fluent.asserts;
449 
450 /// it should get the razer device by name
451 unittest {
452   "0003:1532:0232.0004".getRazerDevice.usbPid.should.equal(0x0232);
453 }