12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249 |
- /*
- Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
- Copyright (C) 2020-2022 Collabora Ltd.
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely.
- */
- /* Hack #1: avoid inclusion of SDL_main.h by SDL_internal.h */
- #define SDL_main_h_
- /* Hack #2: avoid dynapi renaming (must be done before #include <SDL3/SDL.h>) */
- #include "../src/dynapi/SDL_dynapi.h"
- #ifdef SDL_DYNAMIC_API
- #undef SDL_DYNAMIC_API
- #endif
- #define SDL_DYNAMIC_API 0
- #ifndef NO_BUILD_CONFIG
- #include "../src/SDL_internal.h"
- #endif
- /* Hack #3: undo Hack #1 */
- #ifdef SDL_main_h_
- #undef SDL_main_h_
- #endif
- #ifdef SDL_MAIN_NOIMPL
- #undef SDL_MAIN_NOIMPL
- #endif
- #include <SDL3/SDL.h>
- #include <SDL3/SDL_main.h>
- #include <SDL3/SDL_test.h>
- #include <stdio.h>
- #include <string.h>
- static int run_test(void);
- /* FIXME: Need CMake tests for this */
- #if (defined(HAVE_LIBUDEV_H) || defined(SDL_JOYSTICK_LINUX)) && defined(HAVE_LINUX_INPUT_H)
- #include <stdint.h>
- #include "../src/core/linux/SDL_evdev_capabilities.h"
- #include "../src/core/linux/SDL_evdev_capabilities.c"
- static const struct
- {
- int code;
- const char *name;
- } device_classes[] = {
- #define CLS(x) \
- { \
- SDL_UDEV_DEVICE_##x, #x \
- }
- CLS(MOUSE),
- CLS(KEYBOARD),
- CLS(HAS_KEYS),
- CLS(JOYSTICK),
- CLS(SOUND),
- CLS(TOUCHSCREEN),
- CLS(ACCELEROMETER),
- CLS(TOUCHPAD),
- #undef CLS
- { 0, NULL }
- };
- typedef struct
- {
- const char *name;
- const char *eviocgname;
- const char *usb_vendor_name;
- const char *usb_product_name;
- uint16_t bus_type;
- uint16_t vendor_id;
- uint16_t product_id;
- uint16_t version;
- uint16_t usb_device_version;
- uint8_t ev[(EV_MAX + 1) / 8];
- uint8_t keys[(KEY_MAX + 1) / 8];
- uint8_t abs[(ABS_MAX + 1) / 8];
- uint8_t rel[(REL_MAX + 1) / 8];
- uint8_t ff[(FF_MAX + 1) / 8];
- uint8_t props[(INPUT_PROP_MAX + 1) / 8];
- int expected;
- const char *todo;
- size_t hid_report_descriptor_length;
- const unsigned char *hid_report_descriptor;
- } GuessTest;
- /*
- * Test-cases for guessing a device type from its capabilities.
- *
- * The bytes in ev, etc. are in little-endian byte order
- * Trailing zeroes can be omitted.
- *
- * The evemu-describe tool is a convenient way to add a test-case for
- * a physically available device. To contribute new test-cases, see:
- * https://github.com/libsdl-org/SDL/issues/7801#issuecomment-1589114910
- */
- #define ZEROx4 0, 0, 0, 0
- #define ZEROx8 ZEROx4, ZEROx4
- #define FFx4 0xff, 0xff, 0xff, 0xff
- #define FFx8 FFx4, FFx4
- static unsigned char xbox_one_elite_2_hid_report_descriptor[] =
- {
- /* Generic Desktop / Game Pad, Generic Desktop / Keyboard */
- 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01,
- 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31,
- 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95,
- 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x09, 0x01,
- 0xa1, 0x00, 0x09, 0x32, 0x09, 0x35, 0x15, 0x00,
- 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75,
- 0x10, 0x81, 0x02, 0xc0, 0x05, 0x02, 0x09, 0xc5,
- 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75,
- 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75,
- 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x02, 0x09,
- 0xc4, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01,
- 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00,
- 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01,
- 0x09, 0x39, 0x15, 0x01, 0x25, 0x08, 0x35, 0x00,
- 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04,
- 0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01,
- 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00,
- 0x65, 0x00, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01,
- 0x29, 0x0f, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01,
- 0x95, 0x0f, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00,
- 0x75, 0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x0c,
- 0x0a, 0xb2, 0x00, 0x15, 0x00, 0x25, 0x01, 0x95,
- 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25,
- 0x00, 0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x05,
- 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x0a, 0x85, 0x00,
- 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75,
- 0x08, 0x81, 0x02, 0x0a, 0x99, 0x00, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x04, 0x81,
- 0x02, 0x15, 0x00, 0x25, 0x00, 0x95, 0x01, 0x75,
- 0x04, 0x81, 0x03, 0x0a, 0x81, 0x00, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x04, 0x81,
- 0x02, 0x15, 0x00, 0x25, 0x00, 0x95, 0x01, 0x75,
- 0x04, 0x81, 0x03, 0xc0, 0x05, 0x0f, 0x09, 0x21,
- 0x85, 0x03, 0xa1, 0x02, 0x09, 0x97, 0x15, 0x00,
- 0x25, 0x01, 0x75, 0x04, 0x95, 0x01, 0x91, 0x02,
- 0x15, 0x00, 0x25, 0x00, 0x75, 0x04, 0x95, 0x01,
- 0x91, 0x03, 0x09, 0x70, 0x15, 0x00, 0x25, 0x64,
- 0x75, 0x08, 0x95, 0x04, 0x91, 0x02, 0x09, 0x50,
- 0x66, 0x01, 0x10, 0x55, 0x0e, 0x15, 0x00, 0x26,
- 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02,
- 0x09, 0xa7, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
- 0x08, 0x95, 0x01, 0x91, 0x02, 0x65, 0x00, 0x55,
- 0x00, 0x09, 0x7c, 0x15, 0x00, 0x26, 0xff, 0x00,
- 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0xc0, 0x05,
- 0x0c, 0x09, 0x01, 0x85, 0x0c, 0xa1, 0x01, 0x0a,
- 0x9e, 0x00, 0x15, 0x00, 0x26, 0xff, 0x00, 0x95,
- 0x01, 0x75, 0x08, 0x81, 0x02, 0x0a, 0xa1, 0x00,
- 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75,
- 0x08, 0x81, 0x02, 0x0a, 0xa2, 0x00, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x81,
- 0x02, 0x0a, 0xa3, 0x00, 0x15, 0x00, 0x26, 0xff,
- 0x00, 0x95, 0x01, 0x75, 0x08, 0x81, 0x02, 0xc0,
- 0xc0, 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x85,
- 0x05, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15,
- 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81,
- 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95,
- 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05,
- 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (xbox_one_elite_2, sizeof (xbox_one_elite_2_hid_report_descriptor) == 0720);
- static unsigned char ps3_hid_report_descriptor[] =
- {
- /* Generic Desktop / Joystick */
- 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02,
- 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95,
- 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45,
- 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81,
- 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff,
- 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05,
- 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95,
- 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30,
- 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02,
- 0xc0, 0x05, 0x01, 0x75, 0x08, 0x95, 0x27, 0x09,
- 0x01, 0x81, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09,
- 0x01, 0x91, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09,
- 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02,
- 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02,
- 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95,
- 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
- 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01,
- 0xb1, 0x02, 0xc0, 0xc0, 0x00,
- };
- SDL_COMPILE_TIME_ASSERT (ps3, sizeof (ps3_hid_report_descriptor) == 149);
- /* Same for Steam Deck LCD (jupiter) and OLED (galileo) */
- static unsigned char steam_deck_mouse_hid_report_descriptor[] =
- {
- 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01,
- 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x02,
- 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x02,
- 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x01,
- 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
- 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
- 0x95, 0x01, 0x09, 0x38, 0x81, 0x06, 0x05, 0x0c,
- 0x0a, 0x38, 0x02, 0x95, 0x01, 0x81, 0x06, 0xc0,
- 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (steam_deck_mouse,
- sizeof (steam_deck_mouse_hid_report_descriptor) == 65);
- /* Same for Steam Deck LCD (jupiter) and OLED (galileo) */
- static unsigned char steam_deck_kb_hid_report_descriptor[] =
- {
- 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07,
- 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01,
- 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x81, 0x01,
- 0x19, 0x00, 0x29, 0x65, 0x15, 0x00, 0x25, 0x65,
- 0x75, 0x08, 0x95, 0x06, 0x81, 0x00, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (steam_deck_oled_kb,
- sizeof (steam_deck_kb_hid_report_descriptor) == 39);
- static unsigned char steam_deck_lcd_js_hid_report_descriptor[] =
- {
- 0x06, 0xff, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x15,
- 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x40,
- 0x09, 0x01, 0x81, 0x02, 0x09, 0x01, 0xb1, 0x02,
- 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (steam_deck_lcd_js,
- sizeof (steam_deck_lcd_js_hid_report_descriptor) == 25);
- static unsigned char steam_deck_oled_js_hid_report_descriptor[] =
- {
- 0x06, 0xff, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x09,
- 0x02, 0x09, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00,
- 0x75, 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x06,
- 0x09, 0x07, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
- 0x08, 0x95, 0x40, 0xb1, 0x02, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (steam_deck_oled_js,
- sizeof (steam_deck_oled_js_hid_report_descriptor) == 38);
- static unsigned char vrs_pedals_hid_report_descriptor[] =
- {
- /* Generic Desktop / Joystick */
- 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x05, 0x01,
- 0xa1, 0x02, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31,
- 0x09, 0x32, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00,
- 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00,
- 0x75, 0x10, 0x95, 0x03, 0x81, 0x02, 0x06, 0x00,
- 0xff, 0x09, 0x01, 0x95, 0x39, 0x75, 0x08, 0x26,
- 0xff, 0x00, 0x15, 0x00, 0x81, 0x02, 0xc0, 0x06,
- 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x64,
- 0x95, 0x3f, 0x75, 0x08, 0x26, 0xff, 0x00, 0x15,
- 0x00, 0x09, 0x01, 0x91, 0x02, 0x85, 0x65, 0x95,
- 0x3f, 0x75, 0x08, 0x26, 0xff, 0x00, 0x15, 0x00,
- 0x09, 0x01, 0x81, 0x02, 0xc0, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (vrs_pedals, sizeof (vrs_pedals_hid_report_descriptor) == 0136);
- static unsigned char thinkpad_usb_keyboard_hid_report_descriptor[] =
- {
- /* Generic Desktop / Keyboard */
- 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07,
- 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01,
- 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0x95, 0x08,
- 0x75, 0x01, 0x81, 0x01, 0x05, 0x08, 0x19, 0x01,
- 0x29, 0x03, 0x95, 0x03, 0x75, 0x01, 0x91, 0x02,
- 0x95, 0x01, 0x75, 0x05, 0x91, 0x01, 0x05, 0x07,
- 0x19, 0x00, 0x2a, 0xff, 0x00, 0x15, 0x00, 0x26,
- 0xff, 0x00, 0x95, 0x06, 0x75, 0x08, 0x81, 0x00,
- 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (thinkpad_usb_keyboard, sizeof (thinkpad_usb_keyboard_hid_report_descriptor) == 65);
- static unsigned char thinkpad_usb_trackpoint_hid_report_descriptor[] =
- {
- /* Generic Desktop / Mouse, Generic Desktop / System Control,
- * Consumer Devices / Consumer Control */
- 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x85, 0x01,
- 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01,
- 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03,
- 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05,
- 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31,
- 0x15, 0x81, 0x25, 0x7f, 0x95, 0x02, 0x75, 0x08,
- 0x81, 0x06, 0xc0, 0xc0, 0x05, 0x01, 0x09, 0x80,
- 0xa1, 0x01, 0x85, 0x02, 0x05, 0x01, 0x15, 0x00,
- 0x25, 0x01, 0x95, 0x08, 0x75, 0x01, 0x19, 0x81,
- 0x29, 0x88, 0x81, 0x02, 0xc0, 0x05, 0x0c, 0x09,
- 0x01, 0xa1, 0x01, 0x85, 0x03, 0x95, 0x08, 0x75,
- 0x01, 0x15, 0x00, 0x25, 0x01, 0x09, 0xe9, 0x09,
- 0xea, 0x09, 0xe2, 0x09, 0xb7, 0x09, 0xcd, 0x09,
- 0xb5, 0x09, 0xb6, 0x0a, 0x94, 0x01, 0x81, 0x02,
- 0x09, 0x03, 0xa1, 0x02, 0x05, 0x09, 0x19, 0x10,
- 0x29, 0x17, 0x81, 0x02, 0x05, 0x09, 0x19, 0x18,
- 0x29, 0x1f, 0x81, 0x02, 0xc0, 0x05, 0x08, 0x95,
- 0x02, 0x09, 0x09, 0x09, 0x21, 0x91, 0x02, 0x95,
- 0x01, 0x75, 0x06, 0x91, 0x03, 0xc0, 0x06, 0x01,
- 0xff, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x04, 0x95,
- 0x01, 0x75, 0x08, 0x15, 0x00, 0x26, 0xff, 0x00,
- 0x09, 0x20, 0xb1, 0x03, 0x09, 0x21, 0xb1, 0x03,
- 0x09, 0x22, 0xb1, 0x03, 0x09, 0x23, 0xb1, 0x03,
- 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (thinkpad_usb_trackpoint, sizeof (thinkpad_usb_trackpoint_hid_report_descriptor) == 185);
- static unsigned char heusinkveld_pedals_hid_report_descriptor[] =
- {
- /* Generic Desktop / Joystick */
- 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x33,
- 0x09, 0x34, 0x09, 0x35, 0x15, 0x00, 0x26, 0xff,
- 0x0f, 0x85, 0x01, 0x75, 0x10, 0x95, 0x03, 0x81,
- 0x02, 0x09, 0x00, 0x75, 0x10, 0x95, 0x06, 0x82,
- 0x01, 0x01, 0x85, 0x02, 0x75, 0x10, 0x95, 0x03,
- 0x09, 0x00, 0x09, 0x00, 0xb1, 0x02, 0x85, 0x03,
- 0x75, 0x08, 0x95, 0x03, 0x09, 0x00, 0x82, 0x01,
- 0x01, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (heusinkveld_pedals, sizeof (heusinkveld_pedals_hid_report_descriptor) == 072);
- static unsigned char fanatec_handbrake_hid_report_descriptor[] =
- {
- /* Generic Desktop / Joystick */
- 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x09,
- 0x30, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x01,
- 0x95, 0x03, 0x81, 0x02, 0x06, 0x00, 0xff, 0x09,
- 0x01, 0x95, 0x02, 0x91, 0x02, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (fanatec_handbrake, sizeof (fanatec_handbrake_hid_report_descriptor) == 046);
- static unsigned char xpadneo09_xb1s_hid_report_descriptor[] =
- {
- 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01,
- 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31,
- 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95,
- 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x09, 0x01,
- 0xa1, 0x00, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00,
- 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75,
- 0x10, 0x81, 0x02, 0xc0, 0x05, 0x01, 0x09, 0x32,
- 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75,
- 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75,
- 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09,
- 0x35, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01,
- 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00,
- 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01,
- 0x09, 0x39, 0x15, 0x01, 0x25, 0x08, 0x35, 0x00,
- 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04,
- 0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01,
- 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00,
- 0x65, 0x00, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01,
- 0x29, 0x0c, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01,
- 0x95, 0x0c, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00,
- 0x75, 0x01, 0x95, 0x04, 0x81, 0x03, 0x05, 0x0c,
- 0x0a, 0xb2, 0x00, 0x15, 0x00, 0x25, 0x01, 0x95,
- 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25,
- 0x00, 0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x05,
- 0x0f, 0x09, 0x21, 0x85, 0x03, 0xa1, 0x02, 0x09,
- 0x97, 0x15, 0x00, 0x25, 0x01, 0x75, 0x04, 0x95,
- 0x01, 0x91, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75,
- 0x04, 0x95, 0x01, 0x91, 0x03, 0x09, 0x70, 0x15,
- 0x00, 0x25, 0x64, 0x75, 0x08, 0x95, 0x04, 0x91,
- 0x02, 0x09, 0x50, 0x66, 0x01, 0x10, 0x55, 0x0e,
- 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
- 0x01, 0x91, 0x02, 0x09, 0xa7, 0x15, 0x00, 0x26,
- 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02,
- 0x65, 0x00, 0x55, 0x00, 0x09, 0x7c, 0x15, 0x00,
- 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91,
- 0x02, 0xc0, 0xc0,
- };
- SDL_COMPILE_TIME_ASSERT (xpadneo09_xb1s, sizeof (xpadneo09_xb1s_hid_report_descriptor) == 283);
- /* Test-cases derived from real devices or from Linux kernel source */
- /* *INDENT-OFF* */ /* clang-format off */
- static const GuessTest guess_tests[] =
- {
- {
- .name = "Xbox 360 wired USB controller",
- .eviocgname = "Microsoft X-Box 360 pad",
- .usb_vendor_name = "©Microsoft Corporation",
- .usb_product_name = "Controller",
- /* 8BitDo N30 Pro 2 v0114 via USB-C (with the xpad driver) is
- * reported as 0003:045e:028e v0114, and is functionally equivalent */
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x028e,
- .version = 0x0114,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "X-Box One Elite",
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x02e3,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- { /* Reference: https://github.com/libsdl-org/SDL/issues/7814 */
- .name = "X-Box One Elite 2 via USB",
- /* The same physical device via Bluetooth, 0005:045e:0b22 v0517,
- * is reported differently (below). */
- /* Version 0407 is functionally equivalent. */
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x0b00,
- .version = 0x0511,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* XY (left stick), RX/RY (right stick), Z/RZ (triggers), HAT0 (dpad) */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* BTN_TRIGGER_HAPPY5 up to BTN_TRIGGER_HAPPY8 inclusive are the
- * back buttons (paddles) */
- /* 0x2c0 */ 0xf0,
- },
- },
- { /* Reference: https://github.com/libsdl-org/SDL/issues/7814 */
- .name = "X-Box One Elite 2 via Bluetooth",
- /* The same physical device via USB, 0003:045e:0b00 v0511,
- * is reported differently (above). */
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x0b22,
- .version = 0x0517,
- .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* Android-style mapping:
- * XY (left stick), Z/RZ (right stick), GAS/BRAKE (triggers), HAT0 (dpad) */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* KEY_RECORD is advertised but isn't generated in practice */
- /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00,
- /* KEY_UNKNOWN (240) is reported for the profile selector and all
- * four back buttons (paddles) */
- /* 0xc0 */ ZEROx4, 0x00, 0x00, 0x01, 0x00,
- /* ABXY, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL,
- * THUMBR have their obvious meanings; C and Z are also
- * advertised, but are not generated in practice. */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f,
- },
- .hid_report_descriptor_length = sizeof (xbox_one_elite_2_hid_report_descriptor),
- .hid_report_descriptor = &xbox_one_elite_2_hid_report_descriptor[0],
- },
- {
- .name = "X-Box One S via Bluetooth",
- .bus_type = 0x0005,
- .vendor_id = 0x045e,
- .product_id = 0x02e0,
- .version = 0x1130,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "X-Box One S wired",
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x02ea,
- .version = 0x0301,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "X-Box One S via xpadneo 0.9.x",
- /* Reference: https://github.com/libsdl-org/SDL/issues/7823 */
- .eviocgname = "Xbox Wireless Controller",
- .bus_type = 0x0005,
- .vendor_id = 0x045e,
- .product_id = 0x028e,
- .version = 0x1130,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC, FF */
- .ev = { 0x1b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y
- * plus MISC as a deprecated axis reporting (rz - z) */
- .abs = { 0x3f, 0x00, 0x03, 0x00, 0x00, 0x01 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* BTN_TRIGGER_HAPPY33 up to BTN_TRIGGER_HAPPY36 inclusive:
- * used to represent the current profile */
- /* 0x2c0 */ ZEROx4, 0xf0,
- },
- .hid_report_descriptor_length = sizeof (xpadneo09_xb1s_hid_report_descriptor),
- .hid_report_descriptor = &xpadneo09_xb1s_hid_report_descriptor[0],
- },
- {
- .name = "DualSense (PS5) - gamepad",
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x0ce6,
- .version = 0x111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl,
- * thumbr; note that C and Z don't physically exist */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f,
- },
- },
- {
- .name = "DualSense (PS5) v8111 - gamepad",
- .eviocgname = "Sony Interactive Entertainment Wireless Controller",
- .usb_vendor_name = "Sony Interactive Entertainment",
- .usb_product_name = "Wireless Controller",
- /* Same physical device via Bluetooth is 0005:054c:0ce6 v8100
- * and EVIOCGNAME is just "Wireless Controller", otherwise equivalent */
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x0ce6,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- },
- },
- {
- .name = "DualShock 4 - gamepad",
- /* EVIOCGNAME is just "Wireless Controller" when seen via Bluetooth */
- .eviocgname = "Sony Interactive Entertainment Wireless Controller",
- .usb_vendor_name = "Sony Interactive Entertainment",
- .usb_product_name = "Wireless Controller",
- /* Same physical device via Bluetooth is 0005:054c:09cc v8100,
- * but otherwise equivalent */
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x09cc,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC, FF */
- /* Some versions only have 0x0b, SYN, KEY, ABS, like the
- * Bluetooth example below */
- .ev = { 0x1b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- },
- },
- {
- .name = "DualShock 4 - gamepad via Bluetooth (unknown version)",
- .bus_type = 0x0005,
- .vendor_id = 0x054c,
- .product_id = 0x09cc,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- },
- },
- {
- .name = "DualShock 4 - touchpad",
- /* EVIOCGNAME is just "Wireless Controller Touchpad" when seen via Bluetooth */
- .eviocgname = "Sony Interactive Entertainment Wireless Controller Touchpad",
- .usb_vendor_name = "Sony Interactive Entertainment",
- .usb_product_name = "Wireless Controller",
- /* Same physical device via Bluetooth is 0005:054c:09cc v8100 and is
- * functionally equivalent. */
- /* DualSense (PS5), 0003:054c:0ce6 v8111, is functionally equivalent.
- * Same physical device via Bluetooth is 0005:054c:0ce6 v8100 and also
- * functionally equivalent. */
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x09cc,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_TOUCHPAD,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, multitouch */
- .abs = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x02 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* Left mouse button */
- /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4,
- /* BTN_TOOL_FINGER and some multitouch stuff */
- /* 0x140 */ 0x20, 0x24, 0x00, 0x00
- },
- /* POINTER, BUTTONPAD */
- .props = { 0x05 },
- },
- {
- .name = "DualShock 4 - accelerometer",
- /* EVIOCGNAME is just "Wireless Controller Motion Sensors" when seen via Bluetooth */
- .eviocgname = "Sony Interactive Entertainment Wireless Controller Motion Sensors",
- .usb_vendor_name = "Sony Interactive Entertainment",
- .usb_product_name = "Wireless Controller",
- /* Same physical device via Bluetooth is 0005:054c:09cc v8100 and is
- * functionally equivalent. */
- /* DualSense (PS5), 0003:054c:0ce6 v8111, is functionally equivalent.
- * Same physical device via Bluetooth is 0005:054c:0ce6 v8100 and also
- * functionally equivalent. */
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x09cc,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_ACCELEROMETER,
- /* SYN, ABS, MSC */
- .ev = { 0x19 },
- /* X, Y, Z, RX, RY, RZ */
- .abs = { 0x3f },
- /* ACCELEROMETER */
- .props = { 0x40 },
- },
- {
- .name = "DualShock 4 via USB dongle",
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x0ba0,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, ABS, KEY */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- },
- },
- {
- .name = "DualShock 3 - gamepad",
- .eviocgname = "Sony PLAYSTATION(R)3 Controller",
- .usb_vendor_name = "Sony",
- .usb_product_name = "PLAYSTATION(R)3 Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x0268,
- .version = 0x8111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC, FF */
- .ev = { 0x1b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ */
- .abs = { 0x3f },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* Digital dpad */
- /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00,
- },
- .hid_report_descriptor_length = sizeof (ps3_hid_report_descriptor),
- .hid_report_descriptor = &ps3_hid_report_descriptor[0],
- },
- {
- .name = "DualShock 3 - accelerometer",
- .eviocgname = "Sony PLAYSTATION(R)3 Controller Motion Sensors",
- .usb_vendor_name = "Sony",
- .usb_product_name = "PLAYSTATION(R)3 Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x054c,
- .product_id = 0x0268,
- .expected = SDL_UDEV_DEVICE_ACCELEROMETER,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* X, Y, Z */
- .abs = { 0x07 },
- /* ACCELEROMETER */
- .props = { 0x40 },
- .hid_report_descriptor_length = sizeof (ps3_hid_report_descriptor),
- .hid_report_descriptor = &ps3_hid_report_descriptor[0],
- },
- {
- .name = "Steam Controller - gamepad",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1142,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, HAT0X, HAT0Y, HAT2X, HAT2Y */
- .abs = { 0x1b, 0x00, 0x33 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR, joystick THUMB, joystick THUMB2 */
- /* 0x100 */ ZEROx4, 0x06, 0x00, 0xdb, 0x7f,
- /* GEAR_DOWN, GEAR_UP */
- /* 0x140 */ 0x00, 0x00, 0x03, 0x00, ZEROx4,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* Digital dpad */
- /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00,
- },
- },
- {
- /* Present to support lizard mode, even if no Steam Controller
- * is connected */
- .name = "Steam Controller - dongle",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1142,
- .expected = (SDL_UDEV_DEVICE_HAS_KEYS
- | SDL_UDEV_DEVICE_KEYBOARD
- | SDL_UDEV_DEVICE_MOUSE),
- /* SYN, KEY, REL, MSC, LED, REP */
- .ev = { 0x17, 0x00, 0x12 },
- /* X, Y, mouse wheel, high-res mouse wheel */
- .rel = { 0x03, 0x09 },
- .keys = {
- /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4,
- /* 0x40 */ 0xff, 0xff, 0xcf, 0x01, 0xdf, 0xff, 0x80, 0xe0,
- /* 0x80 */ ZEROx8,
- /* 0xc0 */ ZEROx8,
- /* 0x100 */ 0x00, 0x00, 0x1f, 0x00, ZEROx4,
- },
- },
- {
- .name = "Steam Deck - mouse",
- /* This is the LCD model (jupiter).
- * Steam Deck OLED (galileo, possibly pre-production) has
- * .eviocgname = "Valve Software Steam Controller"
- * .version = 0x0110
- * .usb_device_version = 0x0300
- * but is otherwise equivalent.
- */
- .eviocgname = "Valve Software Steam Deck Controller",
- .usb_vendor_name = "Valve Software",
- .usb_product_name = "Steam Deck Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1205,
- .version = 0x011,
- .usb_device_version = 0x0200,
- /* SYN, KEY, REL, MSC */
- .ev = { 0x17 },
- /* X, Y, mouse wheel v/h, high-res mouse wheel v/h */
- .rel = { 0x43, 0x19 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* left/right mouse button */
- /* 0x100 */ 0x00, 0x00, 0x03, 0x00, ZEROx4,
- },
- .expected = SDL_UDEV_DEVICE_MOUSE,
- .hid_report_descriptor_length = sizeof (steam_deck_mouse_hid_report_descriptor),
- .hid_report_descriptor = &steam_deck_mouse_hid_report_descriptor[0],
- },
- {
- .name = "Steam Deck - keyboard",
- /* This is the LCD model (jupiter).
- * Steam Deck OLED (galileo, possibly pre-production) has
- * .eviocgname = "Valve Software Steam Controller"
- * .version = 0x0110
- * .usb_device_version = 0x0300
- * but is otherwise equivalent.
- */
- .eviocgname = "Valve Software Steam Deck Controller",
- .usb_vendor_name = "Valve Software",
- .usb_product_name = "Steam Deck Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1205,
- .version = 0x0110,
- .usb_device_version = 0x0300,
- /* SYN, KEY, MSC, REP */
- .ev = { 0x13, 0x00, 0x10 },
- .keys = {
- /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4,
- /* 0x40 */ 0xff, 0xff, 0xcf, 0x01, 0xdf, 0xff, 0x80, 0xe0,
- },
- .expected = SDL_UDEV_DEVICE_KEYBOARD | SDL_UDEV_DEVICE_HAS_KEYS,
- .hid_report_descriptor_length = sizeof (steam_deck_kb_hid_report_descriptor),
- .hid_report_descriptor = &steam_deck_kb_hid_report_descriptor[0],
- },
- {
- .name = "Steam Deck LCD - gamepad",
- .eviocgname = "Valve Software Steam Deck Controller",
- .usb_vendor_name = "Valve Software",
- .usb_product_name = "Steam Deck Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1205,
- .version = 0x0111,
- .usb_device_version = 0x0200,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* TODO: The data I have for Steam Deck LCD didn't seem to have
- * an evdev device available, so this is extrapolated from
- * kernel source code as being the same as the OLED model
- * (the kernel driver doesn't distinguish). */
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, hat 0-2 x/y */
- .abs = { 0x1b, 0x00, 0x3f },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 0x120 0x46: joystick THUMB, THUMB2, BASE */
- /* 0x130 0xdb: gamepad ABXY, TL/TR */
- /* 0x138 0x7f: gamepad TL2/TR2, SELECT/START, MODE, THUMBL/R */
- /* 0x100 */ ZEROx4, 0x46, 0x00, 0xdb, 0x7f,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x220 0x0f: dpad up/down/left/right */
- /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* 0x2c0 0x0f: joystick TRIGGER_HAPPY1..TRIGGER_HAPPY4 */
- /* 0x2c0 */ 0x0f,
- },
- .hid_report_descriptor_length = sizeof (steam_deck_lcd_js_hid_report_descriptor),
- .hid_report_descriptor = &steam_deck_lcd_js_hid_report_descriptor[0],
- },
- {
- .name = "Steam Deck OLED - gamepad",
- .eviocgname = "Valve Software Steam Controller",
- .usb_vendor_name = "Valve Software",
- .usb_product_name = "Steam Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x1205,
- .version = 0x0110,
- .usb_device_version = 0x0300,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, hat 0-2 x/y */
- .abs = { 0x1b, 0x00, 0x3f },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 0x120 0x46: joystick THUMB, THUMB2, BASE */
- /* 0x130 0xdb: gamepad ABXY, TL/TR */
- /* 0x138 0x7f: gamepad TL2/TR2, SELECT/START, MODE, THUMBL/R */
- /* 0x100 */ ZEROx4, 0x46, 0x00, 0xdb, 0x7f,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x220 0x0f: dpad up/down/left/right */
- /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* 0x2c0 0x0f: joystick TRIGGER_HAPPY1..TRIGGER_HAPPY4 */
- /* 0x2c0 */ 0x0f,
- },
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .hid_report_descriptor_length = sizeof (steam_deck_oled_js_hid_report_descriptor),
- .hid_report_descriptor = &steam_deck_oled_js_hid_report_descriptor[0],
- },
- {
- .name = "Steam Input virtual controller",
- .eviocgname = "Microsoft X-Box 360 pad 0",
- .bus_type = 0x0003,
- .vendor_id = 0x28de,
- .product_id = 0x11ff,
- .version = 0x0001,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* XYZ, RXYZ, hat 0 */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 0x130 0xdb: gamepad ABXY, TL/TR */
- /* 0x138 0x7f: gamepad SELECT/START, MODE, THUMBL/R */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "Guitar Hero for PS3",
- /* SWITCH CO.,LTD. Controller (Dinput) off-brand N64-style USB controller
- * 0003:2563:0575 v0111 is functionally equivalent.
- * https://linux-hardware.org/?id=usb:2563-0575 reports the same IDs as
- * ShenZhen ShanWan Technology ZD-V+ Wired Gaming Controller */
- .bus_type = 0x0003,
- .vendor_id = 0x12ba,
- .product_id = 0x0100,
- .version = 0x0110,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x1f,
- },
- },
- {
- .name = "G27 Racing Wheel, 0003:046d:c29b v0111",
- .bus_type = 0x0003,
- .vendor_id = 0x046d,
- .product_id = 0xc29b,
- .version = 0x0111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */
- /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* TRIGGER_HAPPY1..TRIGGER_HAPPY7 */
- /* 0x2c0 */ 0x7f,
- },
- },
- {
- .name = "Logitech Driving Force, 0003:046d:c294 v0100",
- .bus_type = 0x0003,
- .vendor_id = 0x046d,
- .product_id = 0xc294,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RZ, HAT0X, HAT0Y */
- .abs = { 0x23, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6 */
- /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00,
- },
- },
- {
- .name = "Logitech Dual Action",
- .bus_type = 0x0003,
- .vendor_id = 0x046d,
- .product_id = 0xc216,
- .version = 0x0110,
- /* Logitech RumblePad 2 USB, 0003:046d:c218 v0110, is the same
- * except for having force feedback, which we don't use in our
- * heuristic */
- /* Jess Tech GGE909 PC Recoil Pad, 0003:0f30:010b v0110, is the same */
- /* 8BitDo SNES30 via USB, 0003:2dc8:ab20 v0110, is the same;
- * see below for the same physical device via Bluetooth,
- * 0005:2dc8:2840 v0100 */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6 */
- /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00,
- },
- },
- {
- .name = "8BitDo SNES30 v0100 via Bluetooth",
- .eviocgname = "8Bitdo SNES30 GamePad",
- /* The same physical device via USB, 0003:2dc8:ab20 v0110,
- * is reported differently (above). */
- /* 8BitDo NES30 Pro (aka N30 Pro) via Bluetooth, 0005:2dc8:3820 v0100,
- * is functionally equivalent; but the same physical device via USB,
- * 0003:2dc8:9001 v0111, matches N30 Pro 2 v0111. */
- .bus_type = 0x0005,
- .vendor_id = 0x2dc8,
- .product_id = 0x2840,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* XYZ, RZ, GAS, BRAKE, HAT0X, HAT0Y */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR,
- * and an unassigned button code */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff,
- },
- },
- {
- .name = "Saitek ST290 Pro flight stick",
- .bus_type = 0x0003,
- .vendor_id = 0x06a3,
- .product_id = 0x0160, /* 0x0460 seems to be the same */
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE */
- /* 0x100 */ ZEROx4, 0x3f, 0x00, 0x00, 0x00,
- },
- },
- {
- .name = "Saitek X52 Pro Flight Control System",
- .bus_type = 0x0003,
- .vendor_id = 0x06a3,
- .product_id = 0x0762,
- .version = 0x0111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .ev = { 0x0b },
- /* XYZ, RXYZ, throttle, hat0, MISC, unregistered event code 0x29 */
- .abs = { 0x7f, 0x00, 0x03, 0x00, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */
- /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* TRIGGER_HAPPY1..TRIGGER_HAPPY23 */
- /* 0x2c0 */ 0xff, 0xff, 0x7f,
- },
- },
- {
- .name = "Logitech Extreme 3D",
- .bus_type = 0x0003,
- .vendor_id = 0x046d,
- .product_id = 0xc215,
- .version = 0x0110,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x0b },
- /* X, Y, RZ, throttle, hat 0 */
- .abs = { 0x63, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 12 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6 */
- /* 0x100 */ ZEROx4, 0xff, 0x0f, 0x00, 0x00,
- },
- },
- {
- .name = "Hori Real Arcade Pro VX-SA",
- .bus_type = 0x0003,
- .vendor_id = 0x24c6,
- .product_id = 0x5501,
- .version = 0x0533,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, hat 0 */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- /* https://github.com/ValveSoftware/steam-devices/pull/42
- * PS4 mode is functionally equivalent, but with product ID 0x011c
- * and version 0x1101. */
- .name = "Hori Fighting Stick Alpha - PS5 mode",
- .bus_type = 0x0003, /* USB */
- .vendor_id = 0x0f0d, /* Hori Co., Ltd. */
- .product_id = 0x0184, /* HORI FIGHTING STICK α (PS5 mode) */
- .version = 0x0111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f,
- },
- },
- { /* https://github.com/ValveSoftware/steam-devices/pull/42 */
- .name = "Hori Fighting Stick Alpha - PC mode",
- .bus_type = 0x0003, /* USB */
- .vendor_id = 0x0f0d, /* Hori Co., Ltd. */
- .product_id = 0x011e, /* HORI FIGHTING STICK α (PC mode) */
- .version = 0x0116,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- { /* https://github.com/ValveSoftware/steam-devices/issues/29 */
- .name = "HORIPAD S for Nintendo",
- .bus_type = 0x0003, /* USB */
- .vendor_id = 0x0f0d, /* Hori Co., Ltd. */
- .product_id = 0x00dc, /* HORIPAD S */
- .version = 0x0112,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, FF */
- .ev = { 0x0b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "Switch Pro Controller via Bluetooth",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x2009,
- .version = 0x0001,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, hat 0 */
- .abs = { 0x1b, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */
- /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* TRIGGER_HAPPY1..TRIGGER_HAPPY2 */
- /* 0x2c0 */ 0x03,
- },
- },
- {
- .name = "Switch Pro Controller via Bluetooth (Linux 6.2.11)",
- .eviocgname = "Pro Controller",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x2009,
- .version = 0x0001,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, hat 0 */
- .abs = { 0x1b, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR,
- * and an unassigned button code */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff,
- },
- },
- {
- .name = "Switch Pro Controller via USB",
- .eviocgname = "Nintendo Co., Ltd. Pro Controller",
- .usb_vendor_name = "Nintendo Co., Ltd.",
- .usb_product_name = "Pro Controller",
- .bus_type = 0x0003,
- .vendor_id = 0x057e,
- .product_id = 0x2009,
- .version = 0x0111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* 16 buttons: TRIGGER, THUMB, THUMB2, TOP, TOP2, PINKIE, BASE,
- * BASE2..BASE6, unregistered event codes 0x12c-0x12e, DEAD */
- /* 0x100 */ ZEROx4, 0xff, 0xff, 0x00, 0x00,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* TRIGGER_HAPPY1..TRIGGER_HAPPY2 */
- /* 0x2c0 */ 0x03,
- },
- },
- { /* https://github.com/ValveSoftware/steam-devices/pull/40 */
- .name = "PDP wired Pro Controller for Switch",
- /* 0003:0e6f:0184 "Performance Designed Products" /
- * "Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch" appears
- * to be functionally equivalent */
- .eviocgname = "PDP CO.,LTD. Faceoff Wired Pro Controller for Nintendo Switch",
- .usb_vendor_name = "PDP CO.,LTD.",
- .usb_product_name = "Faceoff Wired Pro Controller for Nintendo Switch",
- .bus_type = 0x0003,
- .vendor_id = 0x0e6f,
- .product_id = 0x0180,
- .version = 0x0111,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* X, Y, Z, RZ, HAT0X, HAT0Y */
- .abs = { 0x27, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f,
- },
- },
- {
- .name = "NES Controller (R) NES-style Joycon from Nintendo Online",
- .eviocgname = "NES Controller (R)",
- /* Joy-Con (L), 0005:057e:2006 v0001, is functionally equivalent.
- * Ordinary Joy-Con (R) and NES-style Joy-Con (L) are assumed to be
- * functionally equivalent as well. */
- .bus_type = 0x0005, /* Bluetooth-only */
- .vendor_id = 0x057e,
- .product_id = 0x2007,
- .version = 0x0001,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY, hat 0 */
- .abs = { 0x1b, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE, THUMBL, THUMBR,
- * and an unassigned button code */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0xff,
- },
- },
- {
- .name = "Thrustmaster Racing Wheel FFB",
- /* Several devices intended for PS4 are functionally equivalent to this:
- * https://github.com/ValveSoftware/steam-devices/pull/34
- * Mad Catz FightStick TE S+ PS4, 0003:0738:8384:0111 v0111
- * (aka Street Fighter V Arcade FightStick TES+)
- * Mad Catz FightStick TE2+ PS4, 0003:0738:8481 v0100
- * (aka Street Fighter V Arcade FightStick TE2+)
- * Bigben Interactive DAIJA Arcade Stick, 0003:146b:0d09 v0111
- * (aka Nacon Daija PS4 Arcade Stick)
- * Razer Razer Raiju Ultimate Wired, 0003:1532:1009 v0000
- * Razer Razer Raiju Ultimate (Bluetooth), 0005:1532:1009 v0001
- */
- .bus_type = 0x0003,
- .vendor_id = 0x044f,
- .product_id = 0xb66d,
- .version = 0x0110,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .ev = { 0x0b },
- /* XYZ, RXYZ, hat 0 */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x3f,
- },
- },
- {
- .name = "Thrustmaster T.Flight Hotas X",
- .bus_type = 0x0003,
- .vendor_id = 0x044f,
- .product_id = 0xb108,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .ev = { 0x0b },
- /* XYZ, RZ, throttle, hat 0 */
- .abs = { 0x67, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* trigger, thumb, thumb2, top, top2, pinkie, base,
- * base2..base6 */
- /* 0x100 */ ZEROx4, 0xff, 0x0f
- },
- },
- {
- .name = "8BitDo N30 Pro via Bluetooth",
- /* This device has also been seen reported with an additional
- * unassigned button code, the same as the SNES30 v0100 via Bluetooth */
- .bus_type = 0x0005,
- .vendor_id = 0x2dc8,
- .product_id = 0x3820,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* XYZ, RZ, gas, brake, hat0 */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl,
- * thumbr */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f,
- },
- },
- {
- .name = "8BitDo N30 Pro 2 v0111",
- .bus_type = 0x0003,
- .vendor_id = 0x2dc8,
- .product_id = 0x9015,
- .version = 0x0111,
- /* 8BitDo NES30 Pro via USB, 0003:2dc8:9001 v0111, is the same;
- * but the same physical device via Bluetooth, 0005:2dc8:3820 v0100,
- * matches 8BitDo SNES30 v0100 via Bluetooth instead (see above). */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .ev = { 0x0b },
- /* XYZ, RZ, gas, brake, hat0 */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl,
- * thumbr */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f,
- },
- },
- {
- .name = "8BitDo N30 Pro 2 via Bluetooth",
- /* Physically the same device as the one that mimics an Xbox 360
- * USB controller when wired */
- .bus_type = 0x0005,
- .vendor_id = 0x045e,
- .product_id = 0x02e0,
- .version = 0x0903,
- .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, ABS, MSC, FF */
- .ev = { 0x1b, 0x00, 0x20 },
- /* X, Y, Z, RX, RY, RZ, HAT0X, HAT0Y */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* KEY_MENU */
- /* 0x80 */ 0x00, 0x08, 0x00, 0x00, ZEROx4,
- /* 0xc0 */ ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2 */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x03,
- },
- },
- {
- .name = "Retro Power SNES-style controller, 0003:0079:0011 v0110",
- .bus_type = 0x0003,
- .vendor_id = 0x0079,
- .product_id = 0x0011,
- .version = 0x0110,
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .ev = { 0x0b },
- /* X, Y */
- .abs = { 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* trigger, thumb, thumb2, top, top2, pinkie, base,
- * base2..base4 */
- /* 0x100 */ ZEROx4, 0xff, 0x03, 0x00, 0x00,
- },
- },
- {
- .name = "Google Stadia Controller rev.A",
- .eviocgname = "Google LLC Stadia Controller rev. A",
- .usb_vendor_name = "Google LLC",
- .usb_product_name = "Stadia Controller rev. A",
- /* This data is with USB-C, but the same physical device via Bluetooth,
- * 0005:18d1:9400 v0000, is functionally equivalent other than having
- * EVIOCGNAME = StadiaXXXX-YYYY where XXXX is the last 4 digits of
- * the serial number and YYYY is some other mystery number */
- .bus_type = 0x0003,
- .vendor_id = 0x18d1,
- .product_id = 0x9400,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS,
- .ev = { 0x0b },
- /* XYZ, RZ, gas, brake, hat0 */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* Volume up/down */
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0c, 0x00,
- /* Media play/pause */
- /* 0x80 */ ZEROx4, 0x10, 0x00, 0x00, 0x00,
- /* 0xc0 */ ZEROx8,
- /* ABXY, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- /* 0x280 */ ZEROx8,
- /* TRIGGER_HAPPY 1-4 */
- /* 0x2c0 */ 0x0f, 0x00, 0x00, 0x00, ZEROx4,
- },
- },
- {
- .name = "Microsoft Xbox Series S|X Controller (model 1914) via USB",
- .eviocgname = "Microsoft Xbox Series S|X Controller",
- .usb_vendor_name = "Microsoft",
- .usb_product_name = "Controller",
- /* Physically the same device as 0003:045e:0b13 v0515 below,
- * but some functionality is mapped differently */
- .bus_type = 0x0003,
- .vendor_id = 0x045e,
- .product_id = 0x0b12,
- .version = 0x050f,
- .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS,
- .ev = { 0x0b },
- /* X, Y, Z, RX, RY, RZ, hat 0 */
- .abs = { 0x3f, 0x00, 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* Record */
- /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00,
- /* 0xc0 */ ZEROx8,
- /* ABXY, TL, TR, SELECT, START, MODE, THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7c,
- },
- },
- {
- .name = "Microsoft Xbox Series S|X Controller (model 1914) via Bluetooth",
- .eviocgname = "Xbox Wireless Controller",
- /* Physically the same device as 0003:045e:0b12 v050f above,
- * but some functionality is mapped differently */
- .bus_type = 0x0005,
- .vendor_id = 0x045e,
- .product_id = 0x0b13,
- .version = 0x0515,
- .expected = SDL_UDEV_DEVICE_JOYSTICK | SDL_UDEV_DEVICE_HAS_KEYS,
- .ev = { 0x0b },
- /* XYZ, RZ, gas, brake, hat0 */
- .abs = { 0x27, 0x06, 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* Record */
- /* 0x80 */ ZEROx4, 0x80, 0x00, 0x00, 0x00,
- /* 0xc0 */ ZEROx8,
- /* ABC, XYZ, TL, TR, TL2, TR2, select, start, mode, thumbl,
- * thumbr */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xff, 0x7f,
- },
- },
- {
- .name = "Wiimote - buttons",
- .eviocgname = "Nintendo Wii Remote",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- /* This one is a bit weird because some of the buttons are mapped
- * to the arrow, page up and page down keys, so it's a joystick
- * with a subset of a keyboard attached. */
- /* TODO: Should this be JOYSTICK, or even JOYSTICK|HAS_KEYS? */
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, FF */
- .ev = { 0x03, 0x00, 0x20 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* left, right, up down */
- /* 0x40 */ ZEROx4, 0x80, 0x16, 0x00, 0x00,
- /* 0x80 */ ZEROx8,
- /* 0xc0 */ ZEROx8,
- /* BTN_1, BTN_2, BTN_A, BTN_B, BTN_MODE */
- /* 0x100 */ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10,
- /* 0x140 */ ZEROx8,
- /* next (keyboard page down), previous (keyboard page up) */
- /* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4,
- },
- },
- {
- .name = "Wiimote - accelerometer",
- .eviocgname = "Nintendo Wii Remote Accelerometer",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- .expected = SDL_UDEV_DEVICE_ACCELEROMETER,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* RX, RY, RZ - even though it would more conventionally be X, Y, Z */
- .abs = { 0x38 },
- },
- {
- .name = "Wiimote - Motion Plus gyroscope",
- .eviocgname = "Nintendo Wii Remote Motion Plus",
- /* Note that if we only look at the bus type, vendor, product, version
- * and axes, this is indistinguishable from the accelerometer */
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- .expected = SDL_UDEV_DEVICE_ACCELEROMETER,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* RX, RY, RZ */
- .abs = { 0x38 },
- },
- {
- .name = "Wiimote - IR positioning",
- .eviocgname = "Nintendo Wii Remote IR",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* HAT0X, Y to HAT3X, Y */
- .abs = { 0x00, 0x00, 0xff },
- },
- {
- .name = "Wiimote - Nunchuck",
- .eviocgname = "Nintendo Wii Remote Nunchuk",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- /* TODO: Should this be JOYSTICK? It has one stick and two buttons */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* RX, RY, RZ, hat 0 - even though this is an accelerometer, which
- * would more conventionally be X, Y, Z, and a left joystick, which
- * would more conventionally be X, Y */
- .abs = { 0x38, 0x00, 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* C and Z buttons */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0x24, 0x00,
- },
- },
- {
- .name = "Wiimote - Classic Controller",
- .eviocgname = "Nintendo Wii Remote Classic Controller",
- .bus_type = 0x0005,
- .vendor_id = 0x057e,
- .product_id = 0x0306,
- .version = 0x0600,
- /* TODO: Should this be JOYSTICK, or maybe JOYSTICK|HAS_KEYS?
- * It's unusual in the same ways as the Wiimote */
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* Hat 1-3 X and Y */
- .abs = { 0x00, 0x00, 0xfc },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* left, right, up down */
- /* 0x40 */ ZEROx4, 0x80, 0x16, 0x00, 0x00,
- /* 0x80 */ ZEROx8,
- /* 0xc0 */ ZEROx8,
- /* A, B, X, Y, MODE, TL, TL2, TR, TR2 */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x13,
- /* 0x140 */ ZEROx8,
- /* next (keyboard page down), previous (keyboard page up) */
- /* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4,
- },
- },
- {
- /* Flags guessed from kernel source code, not confirmed with real
- * hardware */
- .name = "Wiimote - Balance Board",
- /* TODO: Should this be JOYSTICK? */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* Hat 0-1 */
- .abs = { 0x00, 0x00, 0x0f },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* BTN_A */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0x01, 0x00,
- },
- },
- {
- /* Flags guessed from kernel source code, not confirmed with real
- * hardware */
- .name = "Wiimote - Wii U Pro Controller",
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, RX, RY */
- .abs = { 0x1b },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* A, B, X, Y, TL, TR, TL2, TR2, SELECT, START, MODE,
- * THUMBL, THUMBR */
- /* 0x100 */ ZEROx4, 0x00, 0x00, 0xdb, 0x7f,
- /* 0x140 */ ZEROx8,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ ZEROx8,
- /* Digital dpad */
- /* 0x200 */ ZEROx4, 0x0f, 0x00, 0x00, 0x00,
- },
- },
- {
- .name = "Synaptics TM3381-002 (Thinkpad X280 trackpad)",
- .eviocgname = "Synaptics TM3381-002",
- .bus_type = 0x001d, /* BUS_RMI */
- .vendor_id = 0x06cb,
- .product_id = 0x0000,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_TOUCHPAD,
- /* SYN, KEY, ABS */
- .ev = { 0x0b },
- /* X, Y, pressure, multitouch */
- .abs = { 0x03, 0x00, 0x00, 0x01, 0x00, 0x80, 0xf3, 0x06 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* Left mouse button */
- /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4,
- /* BTN_TOOL_FINGER and some multitouch gestures */
- /* 0x140 */ 0x20, 0xe5
- },
- /* POINTER, BUTTONPAD */
- .props = { 0x05 },
- },
- {
- .name = "DELL08AF:00 (Dell XPS laptop touchpad)",
- .bus_type = 0x18,
- .vendor_id = 0x6cb,
- .product_id = 0x76af,
- .version = 0x100,
- .ev = { 0x0b },
- .expected = SDL_UDEV_DEVICE_TOUCHPAD,
- /* X, Y, multitouch */
- .abs = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0x02 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* Left mouse button */
- /* 0x100 */ 0x00, 0x00, 0x01, 0x00, ZEROx4,
- /* BTN_TOOL_FINGER and some multitouch gestures */
- /* 0x140 */ 0x20, 0xe5
- },
- /* POINTER, BUTTONPAD */
- .props = { 0x05 },
- },
- {
- .name = "TPPS/2 Elan TrackPoint (Thinkpad X280)",
- .eviocgname = "TPPS/2 Elan TrackPoint",
- .bus_type = 0x0011, /* BUS_I8042 */
- .vendor_id = 0x0002,
- .product_id = 0x000a,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_MOUSE,
- /* SYN, KEY, REL */
- .ev = { 0x07 },
- /* X, Y */
- .rel = { 0x03 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* Left, middle, right mouse buttons */
- /* 0x100 */ 0x00, 0x00, 0x07,
- },
- /* POINTER, POINTING_STICK */
- .props = { 0x21 },
- },
- {
- .name = "Thinkpad ACPI buttons",
- .eviocgname = "ThinkPad Extra Buttons",
- .bus_type = 0x0019,
- .vendor_id = 0x17aa,
- .product_id = 0x5054,
- .version = 0x4101,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, MSC, SW */
- .ev = { 0x33 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01,
- /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0,
- /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00,
- /* 0x100 */ ZEROx8,
- /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, ZEROx4,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ 0x40, 0x00, 0x01, 0x00, ZEROx4,
- },
- },
- {
- .name = "Thinkpad ACPI buttons (Linux 6.1)",
- .eviocgname = "ThinkPad Extra Buttons",
- .bus_type = 0x0019,
- .vendor_id = 0x17aa,
- .product_id = 0x5054,
- .version = 0x4101,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, MSC, SW */
- .ev = { 0x33 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01,
- /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0,
- /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00,
- /* 0x100 */ ZEROx8,
- /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00,
- /* 0x180 */ ZEROx4, 0x00, 0x00, 0x00, 0x70,
- /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, 0x20, 0x00, 0x00, 0x00,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ ZEROx8,
- },
- },
- {
- .name = "PC speaker",
- .eviocgname = "PC Speaker",
- .bus_type = 0x0010, /* BUS_ISA */
- .vendor_id = 0x001f,
- .product_id = 0x0001,
- .version = 0x0100,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, SND */
- .ev = { 0x01, 0x00, 0x04 },
- },
- {
- .name = "HDA Digital PCBeep",
- .eviocgname = "HDA Digital PCBeep",
- .bus_type = 0x0001,
- .vendor_id = 0x10ec,
- .product_id = 0x0257,
- .version = 0x0001,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, SND */
- .ev = { 0x01, 0x00, 0x04 },
- },
- {
- .name = "ALSA headphone detection, etc.",
- .eviocgname = "HDA Intel PCH Mic",
- /* HDA Intel PCH Headphone is functionally equivalent */
- /* HDA Intel PCH HDMI/DP,pcm=3 is functionally equivalent */
- /* HDA Intel PCH HDMI/DP,pcm=7 is functionally equivalent */
- /* HDA Intel PCH HDMI/DP,pcm=8 is functionally equivalent */
- .bus_type = 0x0000,
- .vendor_id = 0x0000,
- .product_id = 0x0000,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, SW */
- .ev = { 0x21 },
- },
- {
- /* Assumed to be a reasonably typical i8042 (PC AT) keyboard */
- .name = "Thinkpad T520 and X280 keyboards",
- /* Steam Deck LCD/OLED keyboard interface is version 0xab83 but
- * otherwise equivalent */
- .eviocgname = "AT Translated Set 2 keyboard",
- .bus_type = 0x0011, /* BUS_I8042 */
- .vendor_id = 0x0001,
- .product_id = 0x0001,
- .version = 0xab54,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD,
- /* SYN, KEY, MSC, LED, REP */
- .ev = { 0x13, 0x00, 0x12 },
- .keys = {
- /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4,
- /* 0x40 */ 0xff, 0xff, 0xef, 0xff, 0xdf, 0xff, 0xff, 0xfe,
- /* 0x80 */ 0x01, 0xd0, 0x00, 0xf8, 0x78, 0x30, 0x80, 0x03,
- /* 0xc0 */ 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00,
- },
- },
- {
- .name = "Thinkpad X280 sleep button",
- .eviocgname = "Sleep Button",
- .bus_type = 0x0019, /* BUS_HOST */
- .vendor_id = 0x0000,
- .product_id = 0x0003,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY */
- .ev = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* KEY_SLEEP */
- /* 0x80 */ 0x00, 0x40,
- },
- },
- {
- /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */
- .name = "ACPI lid switch",
- .eviocgname = "Lid Switch",
- .bus_type = 0x0019, /* BUS_HOST */
- .vendor_id = 0x0000,
- .product_id = 0x0005,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- /* SYN, SW */
- .ev = { 0x21 },
- },
- {
- /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */
- .name = "ACPI power button",
- .eviocgname = "Power Button",
- .bus_type = 0x0019, /* BUS_HOST */
- .vendor_id = 0x0000,
- .product_id = 0x0001,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY */
- .ev = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* KEY_POWER */
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x10, 0x00,
- },
- },
- {
- /* As seen on Thinkpad X280, Steam Deck LCD, Steam Deck OLED */
- .name = "ACPI video bus",
- .eviocgname = "Video Bus",
- .bus_type = 0x0019, /* BUS_HOST */
- .vendor_id = 0x0000,
- .product_id = 0x0006,
- .version = 0x0000,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY */
- .ev = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* 0x80 */ ZEROx8,
- /* brightness control, video mode, display off */
- /* 0xc0 */ ZEROx4, 0x0b, 0x00, 0x3e, 0x00,
- },
- },
- {
- .name = "Thinkpad X280 webcam",
- .eviocgname = "Integrated Camera: Integrated C",
- .usb_vendor_name = "Chicony Electronics Co.,Ltd.",
- .usb_product_name = "Integrated Camera",
- .bus_type = 0x0003,
- .vendor_id = 0x04f2,
- .product_id = 0xb604,
- .version = 0x0027,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY */
- .ev = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx8,
- /* 0x80 */ ZEROx8,
- /* KEY_CAMERA */
- /* 0xc0 */ 0x00, 0x00, 0x10, 0x00, ZEROx4,
- },
- },
- {
- .name = "Thinkpad X280 extra buttons",
- .bus_type = 0x0019, /* BUS_HOST */
- .vendor_id = 0x17aa,
- .product_id = 0x5054,
- .version = 0x4101,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY */
- .ev = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x0e, 0x01,
- /* 0x80 */ 0x00, 0x50, 0x11, 0x51, 0x00, 0x28, 0x00, 0xc0,
- /* 0xc0 */ 0x04, 0x20, 0x10, 0x02, 0x1b, 0x70, 0x01, 0x00,
- /* 0x100 */ ZEROx8,
- /* 0x140 */ ZEROx4, 0x00, 0x00, 0x50, 0x00,
- /* 0x180 */ ZEROx8,
- /* 0x1c0 */ 0x00, 0x00, 0x04, 0x18, ZEROx4,
- /* 0x200 */ ZEROx8,
- /* 0x240 */ 0x40, 0x00, 0x01, 0x00, ZEROx4,
- },
- },
- {
- .name = "Thinkpad USB keyboard with Trackpoint - keyboard",
- .eviocgname = "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint",
- .usb_vendor_name = "Lite-On Technology Corp.",
- .usb_product_name = "ThinkPad USB Keyboard with TrackPoint",
- .bus_type = 0x0003,
- .vendor_id = 0x17ef,
- .product_id = 0x6009,
- .expected = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD,
- /* SYN, KEY, MSC, LED, REP */
- .ev = { 0x13, 0x00, 0x12 },
- .keys = {
- /* 0x00 */ 0xfe, 0xff, 0xff, 0xff, FFx4,
- /* 0x40 */ 0xff, 0xff, 0xef, 0xff, 0xdf, 0xff, 0xbe, 0xfe,
- /* 0x80 */ 0xff, 0x57, 0x40, 0xc1, 0x7a, 0x20, 0x9f, 0xff,
- /* 0xc0 */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
- },
- .hid_report_descriptor_length = sizeof (thinkpad_usb_keyboard_hid_report_descriptor),
- .hid_report_descriptor = &thinkpad_usb_keyboard_hid_report_descriptor[0],
- },
- {
- .name = "Thinkpad USB keyboard with Trackpoint - Trackpoint",
- .eviocgname = "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint",
- .usb_vendor_name = "Lite-On Technology Corp.",
- .usb_product_name = "ThinkPad USB Keyboard with TrackPoint",
- .bus_type = 0x0003,
- .vendor_id = 0x17ef,
- .product_id = 0x6009,
- .version = 0x0110,
- /* For some reason the special keys like mute and wlan toggle
- * show up here instead of, or in addition to, as part of
- * the keyboard - so both udev and SDL report this as having keys too. */
- .expected = SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_HAS_KEYS,
- /* SYN, KEY, REL, MSC, LED */
- .ev = { 0x17, 0x00, 0x02 },
- /* X, Y */
- .rel = { 0x03 },
- .keys = {
- /* 0x00 */ ZEROx8,
- /* 0x40 */ ZEROx4, 0x00, 0x00, 0x1e, 0x00,
- /* 0x80 */ 0x00, 0xcc, 0x11, 0x01, 0x78, 0x40, 0x00, 0xc0,
- /* 0xc0 */ 0x00, 0x20, 0x10, 0x00, 0x0b, 0x50, 0x00, 0x00,
- /* Mouse buttons: left, right, middle, "task" */
- /* 0x100 */ 0x00, 0x00, 0x87, 0x68, ZEROx4,
- /* 0x140 */ ZEROx4, 0x00, 0x00, 0x10, 0x00,
- /* 0x180 */ ZEROx4, 0x00, 0x00, 0x40, 0x00,
- },
- .hid_report_descriptor_length = sizeof (thinkpad_usb_trackpoint_hid_report_descriptor),
- .hid_report_descriptor = &thinkpad_usb_trackpoint_hid_report_descriptor[0],
- },
- { /* https://github.com/ValveSoftware/Proton/issues/5126 */
- .name = "Smarty Co. VRS DirectForce Pro Pedals",
- .bus_type = 0x0003,
- .vendor_id = 0x0483, /* STMicroelectronics */
- .product_id = 0xa3be, /* VRS DirectForce Pro Pedals */
- .version = 0x0111,
- /* TODO: Ideally we would identify this as a joystick, but there
- * isn't currently enough information to do that without a table
- * of known devices. */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .todo = "https://github.com/ValveSoftware/Proton/issues/5126",
- /* SYN, ABS */
- .ev = { 0x09 },
- /* X, Y, Z */
- .abs = { 0x07 },
- .hid_report_descriptor_length = sizeof (vrs_pedals_hid_report_descriptor),
- .hid_report_descriptor = &vrs_pedals_hid_report_descriptor[0],
- },
- { /* https://github.com/ValveSoftware/Proton/issues/5126 */
- .name = "Heusinkveld Heusinkveld Sim Pedals Ultimate",
- .bus_type = 0x0003,
- .vendor_id = 0x30b7, /* Heusinkveld Engineering */
- .product_id = 0x1003, /* Heusinkveld Sim Pedals Ultimate */
- .version = 0x0000,
- /* TODO: Ideally we would identify this as a joystick, but there
- * isn't currently enough information to do that without a table
- * of known devices. */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .todo = "https://github.com/ValveSoftware/Proton/issues/5126",
- /* SYN, ABS */
- .ev = { 0x09 },
- /* RX, RY, RZ */
- .abs = { 0x38 },
- .hid_report_descriptor_length = sizeof (heusinkveld_pedals_hid_report_descriptor),
- .hid_report_descriptor = &heusinkveld_pedals_hid_report_descriptor[0],
- },
- { /* https://github.com/ValveSoftware/Proton/issues/5126 */
- .name = "Vitaly [mega_mozg] Naidentsev ODDOR-handbrake",
- .bus_type = 0x0003,
- .vendor_id = 0x0000,
- .product_id = 0x0000,
- .version = 0x0001,
- /* TODO: Ideally we would identify this as a joystick by it having
- * the joystick-specific THROTTLE axis and TRIGGER/THUMB buttons */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .todo = "https://github.com/ValveSoftware/Proton/issues/5126",
- /* SYN, KEY, ABS, MSC */
- .ev = { 0x1b },
- /* THROTTLE only */
- .abs = { 0x40 },
- .keys = {
- /* 0x00-0xff */ ZEROx8, ZEROx8, ZEROx8, ZEROx8,
- /* TRIGGER = 0x120, THUMB = 0x121 */
- /* 0x100 */ ZEROx4, 0x03, 0x00, 0x00, 0x00,
- },
- },
- { /* https://github.com/ValveSoftware/Proton/issues/5126 */
- .name = "Leo Bodnar Logitech® G25 Pedals",
- .bus_type = 0x0003,
- .vendor_id = 0x1dd2, /* Leo Bodnar Electronics Ltd */
- .product_id = 0x100c,
- .version = 0x0110,
- /* TODO: Ideally we would identify this as a joystick, but there
- * isn't currently enough information to do that without a table
- * of known devices. */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .todo = "https://github.com/ValveSoftware/Proton/issues/5126",
- /* SYN, ABS */
- .ev = { 0x09 },
- /* RX, RY, RZ */
- .abs = { 0x38 },
- },
- { /* https://github.com/ValveSoftware/Proton/issues/5126 */
- .name = "FANATEC ClubSport USB Handbrake",
- .bus_type = 0x0003,
- .vendor_id = 0x0eb7,
- .product_id = 0x1a93,
- .version = 0x0111,
- /* TODO: Ideally we would identify this as a joystick, but there
- * isn't currently enough information to do that without a table
- * of known devices. */
- .expected = SDL_UDEV_DEVICE_JOYSTICK,
- .todo = "https://github.com/ValveSoftware/Proton/issues/5126",
- /* SYN, ABS */
- .ev = { 0x09 },
- /* X only */
- .abs = { 0x01 },
- .hid_report_descriptor_length = sizeof (fanatec_handbrake_hid_report_descriptor),
- .hid_report_descriptor = &fanatec_handbrake_hid_report_descriptor[0],
- },
- { /* Artificial test data, not a real device */
- .name = "Fake accelerometer with fewer than usual axes reported",
- .expected = SDL_UDEV_DEVICE_ACCELEROMETER,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* X only */
- .abs = { 0x01 },
- /* ACCELEROMETER */
- .props = { 0x40 },
- },
- { /* Artificial test data, not a real device */
- .name = "Fake pointing stick with no buttons",
- .expected = SDL_UDEV_DEVICE_MOUSE,
- /* SYN, REL */
- .ev = { 0x05 },
- /* X,Y */
- .rel = { 0x03 },
- /* POINTER, POINTING_STICK */
- .props = { 0x21 },
- },
- { /* Artificial test data, not a real device */
- .name = "Fake buttonpad",
- .expected = SDL_UDEV_DEVICE_TOUCHPAD,
- /* SYN, ABS */
- .ev = { 0x09 },
- /* X,Y */
- .abs = { 0x03 },
- /* POINTER, BUTTONPAD */
- .props = { 0x05 },
- },
- {
- .name = "No information",
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
- }
- };
- /* *INDENT-ON* */ /* clang-format on */
- /* The Linux kernel provides capability info in EVIOCGBIT and in /sys
- * as an array of unsigned long in native byte order, rather than an array
- * of bytes, an array of native-endian 32-bit words or an array of
- * native-endian 64-bit words like you might have reasonably expected.
- * The order of words in the array is always lowest-valued first: for
- * instance, the first unsigned long in abs[] contains the bit representing
- * absolute axis 0 (ABS_X).
- *
- * The constant arrays above provide test data in little-endian, because
- * that's the easiest representation for hard-coding into a test like this.
- * On a big-endian platform we need to byteswap it, one unsigned long at a
- * time, to match what the kernel would produce. This requires us to choose
- * an appropriate byteswapping function for the architecture's word size. */
- SDL_COMPILE_TIME_ASSERT(sizeof_long, sizeof(unsigned long) == 4 || sizeof(unsigned long) == 8);
- #define SwapLongLE(X) \
- ((sizeof(unsigned long) == 4) ? SDL_Swap32LE(X) : SDL_Swap64LE(X))
- static int
- run_test(void)
- {
- int success = 1;
- size_t i;
- for (i = 0; i < SDL_arraysize(guess_tests); i++) {
- const GuessTest *t = &guess_tests[i];
- size_t j;
- int actual;
- struct
- {
- unsigned long props[NBITS(INPUT_PROP_MAX)];
- unsigned long ev[NBITS(EV_MAX)];
- unsigned long abs[NBITS(ABS_MAX)];
- unsigned long keys[NBITS(KEY_MAX)];
- unsigned long rel[NBITS(REL_MAX)];
- } caps;
- printf("%s...\n", t->name);
- SDL_memset(&caps, '\0', sizeof(caps));
- SDL_memcpy(caps.props, t->props, sizeof(t->props));
- SDL_memcpy(caps.ev, t->ev, sizeof(t->ev));
- SDL_memcpy(caps.keys, t->keys, sizeof(t->keys));
- SDL_memcpy(caps.abs, t->abs, sizeof(t->abs));
- SDL_memcpy(caps.rel, t->rel, sizeof(t->rel));
- for (j = 0; j < SDL_arraysize(caps.props); j++) {
- caps.props[j] = SwapLongLE(caps.props[j]);
- }
- for (j = 0; j < SDL_arraysize(caps.ev); j++) {
- caps.ev[j] = SwapLongLE(caps.ev[j]);
- }
- for (j = 0; j < SDL_arraysize(caps.keys); j++) {
- caps.keys[j] = SwapLongLE(caps.keys[j]);
- }
- for (j = 0; j < SDL_arraysize(caps.abs); j++) {
- caps.abs[j] = SwapLongLE(caps.abs[j]);
- }
- for (j = 0; j < SDL_arraysize(caps.rel); j++) {
- caps.rel[j] = SwapLongLE(caps.rel[j]);
- }
- actual = SDL_EVDEV_GuessDeviceClass(caps.props, caps.ev, caps.abs,
- caps.keys, caps.rel);
- if (actual == t->expected) {
- printf("\tOK\n");
- } else {
- printf("\tExpected 0x%08x\n", t->expected);
- for (j = 0; device_classes[j].code != 0; j++) {
- if (t->expected & device_classes[j].code) {
- printf("\t\t%s\n", device_classes[j].name);
- }
- }
- printf("\tGot 0x%08x\n", actual);
- for (j = 0; device_classes[j].code != 0; j++) {
- if (actual & device_classes[j].code) {
- printf("\t\t%s\n", device_classes[j].name);
- }
- }
- if (t->todo) {
- printf("\tKnown issue, ignoring: %s\n", t->todo);
- } else {
- printf("\tFailed\n");
- success = 0;
- }
- }
- }
- return success;
- }
- #else /* !(HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX)) */
- static int
- run_test(void)
- {
- printf("SDL compiled without evdev capability check.\n");
- return 1;
- }
- #endif
- int main(int argc, char *argv[])
- {
- int result;
- SDLTest_CommonState *state;
- /* Initialize test framework */
- state = SDLTest_CommonCreateState(argv, 0);
- if (!state) {
- return 1;
- }
- /* Parse commandline */
- if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
- return 1;
- }
- result = run_test() ? 0 : 1;
- SDL_Quit();
- SDLTest_CommonDestroyState(state);
- return result;
- }
|