From d8b879a4ee844b693af2d7af85e2cd3d6d2712b3 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Thu, 15 Nov 2012 01:09:25 +1300 Subject: [PATCH] Movd back to libusb for full support on windows --- Externals/libusb/include/hidapi.h | 384 ------------------ Externals/libusb/win32/hidapi.lib | Bin 51150 -> 0 bytes Externals/libusb/x64/hidapi.lib | Bin 53880 -> 0 bytes Source/Core/Common/Src/Log.h | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp | 381 ++++++----------- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.h | 25 +- Source/VSProps/Dolphin.x64.props | 2 +- 7 files changed, 143 insertions(+), 651 deletions(-) delete mode 100644 Externals/libusb/include/hidapi.h delete mode 100644 Externals/libusb/win32/hidapi.lib delete mode 100644 Externals/libusb/x64/hidapi.lib diff --git a/Externals/libusb/include/hidapi.h b/Externals/libusb/include/hidapi.h deleted file mode 100644 index 3cd829b54a..0000000000 --- a/Externals/libusb/include/hidapi.h +++ /dev/null @@ -1,384 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -/** @file - * @defgroup API hidapi API - */ - -#ifndef HIDAPI_H__ -#define HIDAPI_H__ - -#include - -#ifdef _WIN32 - #define HID_API_EXPORT __declspec(dllexport) - #define HID_API_CALL -#else - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ -#endif - -#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ - -#ifdef __cplusplus -extern "C" { -#endif - struct hid_device_; - typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ - - /** hidapi info structure */ - struct hid_device_info { - /** Platform-specific device path */ - char *path; - /** Device Vendor ID */ - unsigned short vendor_id; - /** Device Product ID */ - unsigned short product_id; - /** Serial Number */ - wchar_t *serial_number; - /** Device Release Number in binary-coded decimal, - also known as Device Version Number */ - unsigned short release_number; - /** Manufacturer String */ - wchar_t *manufacturer_string; - /** Product string */ - wchar_t *product_string; - /** Usage Page for this Device/Interface - (Windows/Mac only). */ - unsigned short usage_page; - /** Usage for this Device/Interface - (Windows/Mac only).*/ - unsigned short usage; - /** The USB interface which this logical device - represents. Valid on both Linux implementations - in all cases, and valid on the Windows implementation - only if the device contains more than one interface. */ - int interface_number; - - /** Pointer to the next device */ - struct hid_device_info *next; - }; - - - /** @brief Initialize the HIDAPI library. - - This function initializes the HIDAPI library. Calling it is not - strictly necessary, as it will be called automatically by - hid_enumerate() and any of the hid_open_*() functions if it is - needed. This function should be called at the beginning of - execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_init(void); - - /** @brief Finalize the HIDAPI library. - - This function frees all of the static data associated with - HIDAPI. It should be called at the end of execution to avoid - memory leaks. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_exit(void); - - /** @brief Enumerate the HID Devices. - - This function returns a linked list of all the HID devices - attached to the system which match vendor_id and product_id. - If @p vendor_id and @p product_id are both set to 0, then - all HID devices will be returned. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the types of device - to open. - @param product_id The Product ID (PID) of the types of - device to open. - - @returns - This function returns a pointer to a linked list of type - struct #hid_device, containing information about the HID devices - attached to the system, or NULL in the case of failure. Free - this linked list by calling hid_free_enumeration(). - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); - - /** @brief Free an enumeration Linked List - - This function frees a linked list created by hid_enumerate(). - - @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). - */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); - - /** @brief Open a HID device using a Vendor ID (VID), Product ID - (PID) and optionally a serial number. - - If @p serial_number is NULL, the first device with the - specified VID and PID is opened. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the device to open. - @param product_id The Product ID (PID) of the device to open. - @param serial_number The Serial Number of the device to open - (Optionally NULL). - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); - - /** @brief Open a HID device by its path name. - - The path name be determined by calling hid_enumerate(), or a - platform-specific path name can be used (eg: /dev/hidraw0 on - Linux). - - @ingroup API - @param path The path name of the device to open - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); - - /** @brief Write an Output report to a HID device. - - The first byte of @p data[] must contain the Report ID. For - devices which only support a single report, this must be set - to 0x0. The remaining bytes contain the report data. Since - the Report ID is mandatory, calls to hid_write() will always - contain one more byte than the report contains. For example, - if a hid report is 16 bytes long, 17 bytes must be passed to - hid_write(), the Report ID (or 0x0, for devices with a - single report), followed by the report data (16 bytes). In - this example, the length passed in would be 17. - - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); - int HID_API_EXPORT HID_API_CALL hid_write_report(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Read an Input report from a HID device with timeout. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - @param milliseconds timeout in milliseconds or -1 for blocking wait. - - @returns - This function returns the actual number of bytes read and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); - - /** @brief Read an Input report from a HID device. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - - @returns - This function returns the actual number of bytes read and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); - - /** @brief Set the device handle to be non-blocking. - - In non-blocking mode calls to hid_read() will return - immediately with a value of 0 if there is no data to be - read. In blocking mode, hid_read() will wait (block) until - there is data to read before returning. - - Nonblocking can be turned on and off at any time. - - @ingroup API - @param device A device handle returned from hid_open(). - @param nonblock enable or not the nonblocking reads - - 1 to enable nonblocking - - 0 to disable nonblocking. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); - - /** @brief Send a Feature report to the device. - - Feature reports are sent over the Control endpoint as a - Set_Report transfer. The first byte of @p data[] must - contain the Report ID. For devices which only support a - single report, this must be set to 0x0. The remaining bytes - contain the report data. Since the Report ID is mandatory, - calls to hid_send_feature_report() will always contain one - more byte than the report contains. For example, if a hid - report is 16 bytes long, 17 bytes must be passed to - hid_send_feature_report(): the Report ID (or 0x0, for - devices which do not use numbered reports), followed by the - report data (16 bytes). In this example, the length passed - in would be 17. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send, including - the report number. - - @returns - This function returns the actual number of bytes written and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); - - /** @brief Get a feature report from a HID device. - - Make sure to set the first byte of @p data[] to the Report - ID of the report to be read. Make sure to allow space for - this extra byte in @p data[]. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read and - -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); - - /** @brief Close a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); - - /** @brief Get The Manufacturer String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Product String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get The Serial Number String from a HID device. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); - - /** @brief Get a string from a HID device, based on its string index. - - @ingroup API - @param device A device handle returned from hid_open(). - @param string_index The index of the string to get. - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); - - /** @brief Get a string describing the last error which occurred. - - @ingroup API - @param device A device handle returned from hid_open(). - - @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. - */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Externals/libusb/win32/hidapi.lib b/Externals/libusb/win32/hidapi.lib deleted file mode 100644 index 7fbc90bbca71487e188cf871a337db918d55a809..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51150 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 diff --git a/Externals/libusb/x64/hidapi.lib b/Externals/libusb/x64/hidapi.lib deleted file mode 100644 index 0626164cb7fa14c5b1a90f5220bb4afae60bd718..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53880 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%0DFNwaRygdv}J5)uk@cFii+ z&z+T0SGBa0dabI)pxj9rm>YCbLPJI8*P-aOfrhGZho+Y8xL0akyinX(oj^=QXj!MH zf8oXWigss}Te8advwjjY!46tXHGe5#X*Sv`d&I)%mlD*+3Fe|3ggUm` zYp2C=v!W^3`N;})DbgJ;eQ0mLx!Nla6{hoI$dK!*Iz3K9%>3%kPUO^JKdzG&NH^cA z!i}Bv!Igi;Jb6*L?$4MrP%8x+8ai90y1LM^P}pDBNd*TRLkl|Ow%Re@KwW1`0i9rk zZ0OJ!*}mIbT=6H|m#UgipQYj_G`~MxN7?z4LYS}Pb0wX5Fx1poTi3DCtbHAXmIUz+ zRl+qL8%Ek`SW-jh-BO^wqPo+QWaUpLb=KS)f^=IKQp6S5lW;m7<@FR-t5CXl2%%Zb z+pI$A;yr}C%-gF%>7pz48@QR*Lxs}C2!x85ccKcV3l~C#%=4&Fx>$%19**YLKB(yrV6Et?-0sk9_@mlP`b#>px0z5kG?9DE=D4R z?KI$xQlWHlGoI^WYYEO;n<@ zyyxwCTO5%+j-BEVj-6)uVyVd6lD9kW`I;7MFGq_t6XyV&**Hhw%*8ngr}+?`u47MM zi`C(XY;&yGo_+c@lnn2k(0ezf_(lE*A#eVG&uq|fA_I?Yqem5j*vllahe(Ww#?g}DIHf^QC|%sH z^X^t5X%JKnYM3y9HqmBOI+%W}$Vau5{s8wIyTa1?Y*6 zR@uiQyAtCoC_ci86)X{RatAO+b^!Ao73z2Ldc6Y}G|BJEY584DIM9As!p`4`AK6~~ z4||T<^244(yU=AuY+JGG5L5ETWGkuIgD=E94q=lLd+AheSs(L8;g>$1naXa5#-~(a z!!M;z?_?7b3 zBjjct>{{VABUHk?r|>Ir+YzGiE>*mVUn%chgk~`BL;OnIK7KsbZRrvm$f~^PD=)gV0pw(XM4FuL_|l%nRta zAVL$Fw_L}qKxhK2kjuF^l>tTs)@18Go_kDDjMElcsHYs*99b-U#l?udqABV z^BRuM)xP5b`Nsd3sKt+zlWWPazrNF!L$+hKwUlWCJe-VU8<{qB{pg&j z8CPTCOjLF<)nUk%gO}EX9N=OO3E{$mM_7*B>l$MAX=Blm0zdedwKJ z5JLHr8I##k!_)CL%!sbv104eT2`F{w&p`>Z0H-uB3Z=98OWw6AR+<;d)((o7<|RXE zxUOd&o7aUfFB(48sI=<&a5pvn?c_0(#O#nE%y7wt{B$E_M<*+H{k5C-t z^D`)A^9v|8LW*BO2ZR0>bOb0oaWj<#uavN&sR5;;DU{BNm%LhBOCADT52AD|$0-#p zL!{`lnWy(-Xt#tWui1{sPc)Owbwn~85#OYJfMGy)XKI0LEigg_URCrL$EtUmo~OBJ zE*c}-_wBZUNV*PZDyv?G$W~-%ydFAP4`~f^7C2Ml8m1gPvLT|!MVpKoCjQgWzq6j8 z?vV>AA3*OsO${l3&JKM6Vzh(uqK2b<=PKrYGz0~|1|>dSlerxLrK#XS(BYtXwWgVJ z`4)6C=zl;hpx=SgQ2hfaY2yN%vOy_?rKZkXqeAICEugY!$5jZ(29+TckzXN75o9`a z&?JTq(r6STL%qPGiA4&dya;JWGP$jYgxs!OMAvaN=tX5yu2G3HM5Zid8<7-FCR-v+ z>0LznSWK2-cWI86+MLXpv+%{X6<>L1<@!#>W@j&Z#v>m(BL^IjFKNw$wU#XhD^y#K znSLCusn0fcbwqyNKWZQ4rG>~chYWQHwcGZwn7y(YR&*pauJSs9x{y&RFA zHiEuwU-?P6AFb1J;l@d#T9obYAstS}BU@H&X&NjqPX06n{j9Ge@*)eu{IO+a&c(=f zKh|bFU9IxM(OQO~;4u^UG8qIUOVd4~@KgUAMu(G~N#mg}1s##voTcbc9?M+cncHlT zcRS8h?gn>oXaRoj!8(9N-(Q2qN>8ksymBsnl|8YsGIsdDI_#5UCEQ!ZW?29Zo(J@PoV z6r7Wg1|60D6Cy1!o53Py?l#r>>*wRY(GCQYS|FR5xFhJ}!qCQVUVc(Hp>eqX*L)J{TpZ#C}xskG3c|P z%R%1Z{tCJZ)P(Y{2JHcQF(|cN3n)3C>v2lwL!opr55KoCuUduD z1>G=`I9dTn93lnjMLX_7KsqEDg1W?d=9&7Wi9Tf+qR+U)M4u}T+tMr8bDre^6BQEn zC*?(_LuA1x#n~Lmq9X;TQ?nlV847M@_V$cO{DH~Q?FJGNYgU=y#F^Cquwu+gPV#wB zAPdqC5=Qnw<;hXZHP9yoTS19`snYMg2uuA^NZwhHyt{ENdGI-HXoLFWgg>Ya?Y|~d zKSc6mN2irSJ>>T^g17FPDf26pM%F2fJOG~52!+xG=|S>H8)48sQC3B}GhwRZ2agITqS%p~ESPtSF= zx^g@&j5W&3!!u7cy7tk)$?Kg~ZeN3|m$%yBlIOuC z``>~PN2?c^p_ImPK*3`kPpg?qb76S61nVIoFZ*V^~nvDho z?ZD7LZ5`W(XM>ZCDT!fdm9^5)Z!Z)e(Y(k4&nB#yboy{2&lX~ z3XqBah*LYLZq(_I2IDKmyapys^}ZRD>U9ff0qCuuH2B^IO6!?BKpR2t1U(=0ub>x$ zZUDUu^exb9K;H%>_llRP+39Zrr4I2R=#!uifo=hP1av#-Q=spGZUOxmbSvn;LAQa@ z;Qb;fmKEX!&~%iau6t8GK>LCI1N2DHS3$ECe}v+nh;)zOlwFlV>7oX|bbF~MTNj1W zSw|8_!;Qotz_vh?j;%Q5;2=X#qoDfW-Z>8ry)ZcR6n#qN;1IE-{jkS=l=O)`03)H% z5n>Il;@51w!J~r&7bP0t|2#m%8P@=ak1;M9AjnXRMondjA00k`g25L51f??W1tkUV z#3>a_p>!TGCGU0>n~oRE-t8q?_8yGYt^g>*5tP-%D!dKr= zUx{xQEW+M_Kdg^_=qZ^HD?5=UiTjCM>`p?Yc4!KqvQj1K_*g066Hr<+eF{qD{7fn0 zC4{9SD3mU4#INM7SD|z~hQjJVU!q2OI3s(cmtMK0slPUJrn|ZN3UnJDT17AVK~f>k zR9+)V@2BbW2Jlag)2A6cD(iThanp_vO(GD{LWMpJaF2(!;x+L9y2})Dd{h-Hyeg!%V^k1MOKo5fEfgS**y3zHC zps(YUZ9t)PdT63}533MqLkKhf%AY+TvS-T>l?Qi3J`&I8U?>mGY#7lN-Lm<_ti-eTS2Z1Fzoifn!S3RBPM8tPc%NS$RInOAI| zcRJcTW(8(8j=UIhU)5Gt47Q`BpWsa8rP6Q?orzy*8!HgHm3f+#?84QwI4ijpJgW5- zIOALoKGl@WNag{Vcc5v>3D}=xLz6K`TKI1NDO*4Y~-l zFX%;}{Xknl2Y^OE2ZEBm2uGGj3m9p66v6|2owrwoq~%c=wc}F+q~*yFmGfifnbNw5 zv%gWS#!)wmuLnCr(ErL=HHW zpQy^vNw^-yyh-?7$04&G(u{``6Th;d=^9mys5=Wk@}P+m|FK z1Dxbj<5FI86@L(vPr+Ew{aZkG|=IoHqa5E)QDf= zl#NKCbiU^(dCe-8a*=iA0Dfrfl#M7u)QAU|r)~-5${h`|0qrSUbcY|;^RY33Zvlgn z8ofAE@m(~nD{F0V3pn@+VN}z&9*eUZPO8JH(HLq2>cC0+KEDPSe85*mL(4Xwqv4n&}3h>lMGQi(cPcuW|jY~on}E!vUZ|j zGXIbDE4*Zbe|X@lZ>p=r=92$kT1)zy-)k>B^iJ*N0HyYFf>L|U038fk1WN7Y2Br2Y z0i|}LYoZy@v+P$ClKo2Zs9#AQ0x|8?pWBAKlnhaO(E_cl_Ikd9esDVEBx|qD;J4SW zyor7gdnoZ=46FawmZD`ixj>p)xJ|OTeJoRVgbCi!0c@go>`0$0MO#oCmV;6o&IF}4 zoCP`O?C* zDgR2Pis8B{C?tn<$s@Sr(No&ylW~cAantq@S+!-^i5+=vt8KoKk8w@vF)j_qRFSUu z?w=f(Qw23&cbutQV)GthrII)0Fp^sCBrLI{4a&n=2xIJx%w9V_7y1q8jFnie3s{}#;Vs)k($Z&)fuaHAoRFdW$bC4 z@vKyAWKS{fnIGqDDV(%_Sl;)CwvpCQ^2i&y&Q`tg+o3~WT&Gkrj~>N(oRODZksl>w z<(BXm2in8~CB7zEP*Ij>%FNho-;GVtxuCCsj%AcYI9fuJidTIfo=8sW`9sdgZ{OV4 z>M=Qfc-_%@)*&vNtF^#{nmQwIIa*RwX%F9#+8^rPpWMmbuSrjlM~TOQ4%CW^dD<}sTAE!J_4$;)$QH+5HH^s2h>;ADX<0xtj-V=aev zP=}QLGxAEbW7;6jg)`baSDpJSToj&}%yUI#*K|Z=S4HbfRk|X|9Yl6IBCX`Q9C4eWvfsGk9mpLTEabHx{O$2B~5xe#zISiWT^kW6h-q$+6}tokxojnc}Z1 z)Kz?j5N%jY^5PZ}KO=Gk;@<-uoP~fqXn`Kx#>OuYpn;Pd783@{DOs6_ zb(>7s4-nmffagGA(JzjnZoSZkIT{BBL!{fZ7dnoiiP9VQ+<*UbkPv(6U znJ}0^9J2(|ab~>+A@l`vx2dWk7{ceQDK3qjX{mVw>^S`NAibPni0Ku-hx2=ollpFv^$&BvjP z6`-R*(U+U&g4Tl8fHr}i4SEjft)R%Gc{6AW=#!wAfNlX@1G*KI>bD)#4Y~uA%JFwl zD#u5lt)QQSUIF?e=#`+qg02I_T~%=vXdlq4L2p<@U4T5d}T@88t=kxafs4yHTr+g~IQ%O^_Ok||DrUA{nKcgX2!Hsio-PX6PneU zc~&fWJoycyAnKt9Mavj{CyW+{oh_p>FmIoUsbMb)l%WjRTw_R4q_zsvyM*)rR%*o& zS;I=#CuEU_bGDGyF4(>v#J4RIzYC$#RNkyYW|PX(80y}s{O*XHk~wiLr(~pb$)jnE zOi`^uU3q`Aobo&i-T<7bwA@ycDOxYd$9$Ox$%#`ALUQ6n3uYNh9bHbLFr=tS4V=1~ z)CBd|WeDBQd0dN7?4)KV`0BpxvM+tLWqL6aKZ=FfZfX;QPE`3XN3IjJEt zrb*3VhB*vw72$s!L?=18_GyDR?R?&ZG=>)gw08yK27WV8u>(KfOrpDQ`*3Op)q@84 zfndC+n1k@xkm`m>Y;z9iaiFJz4hOAN*8$Muas3?VDA4agb3uOv9SfQYxp|=7KqrFs z1)T)iA9M=n0MKcmBS23EJqh#_P)rEK4A6W~7ibY^F{l@`1eDx_1(c?{`Jfo+>3aWtsTkao-5^&lOA^j12x%{YgD2PQGb-O z392C}oJ_Vv9yzG1=v_TP^fvVs-GYP_f=rZTNe3O>;!REsK5%(XHgEOL#&(X3&EI5f z{=%O330oL8Z@aLC8>>xvFE)_YG#ccr^rqo>&mcUi7+e0}UR)<^%h;TmpRu`@IN|lC zG{=f9T~6_H*MXY>5TNCWo#PDrF%fQgD@>)kc~!#PQ2xS)$Ak( zRMY?-@lII2st3aoz+qJ~eUcafFTxJ3_b&_fUDp(peZHTXfCf591l z|MFAtsLPRS*@PLpIyCq3J5MNSX_Jd2gK@?$Z6@h_!_tQKSDO(*|0V@@?~RXc`gZ2hp2HF?&Jkb82t3i(hCA}OCO5HaC{mbr4p>*-E&ZE&<@(|#y@I>jryj*ol z8KMqyIrB^d)5XAW4>7PhO$;pSE(YSAh=F7KZ=u$jDf;z0>!vqu8qojKlGgYC^4tga z?q5asW%0?0j(?@1(T@*RhWv9ESB=Td9UZK$6bH@t$VzZ@p!%qrHsBq8D%t4jMt@a! zu^+-|B*SAsIIXy2bhW>-X?~8E*c6#!vdxggS`;|CGDJR%4@}>IsZdw3gladN;?*fz zcAm}|%}ZEZ;vj5_3DYt@p6-*!C4hE#361~jgo7}$z(=Vo$r&B?FQqo7qbtr7Qx$#* zxoP)=HL|Y8dQmPZrhD;A>FMao=_oXeesFXZ*`%>xw20loO)-)4r25RhtNP4ns&U}Z z!5A@mX*3ntK#GZe>A3Cgcm5Mi1;z5g7!Dcr*hN&~UmG=0Rrtt8jf^$z0d9(E75(D8 z@yla9i8UoVN-@zesMWNGUQ-RY@FiV5pc_&BuHyAyD$85gkdsP!Jk7@DYQ zb?>d$eIMfJ=$%k^@;%X3K5*dYo1&?H;xy8VVH<{4hKEBct(9M&{9HyfRTdQt2V*!y zYXApA)NYW|7_}C1$|)wQ9UTY1-i2SO9lmS9T*62m-Mb*qn<%FbaZPf##uq1=w!+nF zavD{62qSs7C{CiB!&y#${L(RO?=LVnP0nVOiZGJ*DLABqL^*wlYtrN_f8#p1a!n3A zJRgLSypbSgTqVlsM_dzWl8$-(J~V4-u(MSOB#aDJfMnw;Q4WSE?qNRa;NDVj$BjwbBlZ&fF{m?8SDreWn)Qhz8 zT%_a>M)K&*X3e@~J2rxzqr?RD($Y$u+yX+`*PEGPhDivWQuea89nPZf5G&s>7 zw_!ljOIjMVxk^QtSf63-uF-EYv{CpwOSUB!+L zgTRgYjl-Vnb5}G~kxIpw7{8Itsi@D;arylVZ;qxqQ>DsAj8sgc;t)2rUV{l^Itjl7 zdAH;%G)H{BhA`$)g#p1#jz&wqB~I@sGbfuQ8%DjM;7059b8u$1OhxFGsyvK|saFoC z(&|P2Fq&$eO2rrwBkoWf3U?7Xu99&SqJ!$yEoRiC@j1m*j$bPKLrw0p6Ke|R0?YyY zYJ!L9Ex1{+hM@&xYdV}$X(QB`O+#l!Q@x~8F(#&_+@IMaQ5&6nsB}m))t4%j?DIyg zj*Q9c#qYY=qp8xUVmKHRlh^U!Vl<~;oSR>0J}R2(IF*VqF)erkr_$>6dcUqWL{r&R zD#pa*bt0$ITJV>j1}%!Fnx|4RM$l{20IP$viWZ!tT@OPbwgpFllVTbQ^Q75{xXRa% z*n%{wr%)ROiWGL1F}{rrwKFm_@k+= zSE(4o1=$D=-EN>-$g*u$7>br&>w_3hUBWD`&R1oTrdJJe3GHPrJV_w6r*2EXM8^3g1xVQ(bF<$aC#KhXqRJ|?kQMH(wAenZJq?pY3C7m2T^7EaEk})X(CJh;C zWj{PCYvq4!y=i1L)!Ql+V`5s_tfxXi410ObuxP69RVv2Bj5}0| zSg&OPC&hFveyPl5BT8;btXDo`lICv)dP_@7!y-3szq$Q=75u8QWFBv z|CR4znbLJSu%}` zyj>SDrzdFa3{ItKY{$39mCICMiz%u+jET`0ZXckgn#O3o6HPTkrD6<^|DIyjLDv#>9+hRh&x8>%{BVSfi<~QF$>YCa-EvrR8<)wVzxQO?972#h949 z{4sewb@Jr2XsYK_D#pa*Rl}(U&@axCp{}o@soqnm7!#A%{FuDLjSr2ErutT;VoXe4 z3piC@l~=!vHBUrSrSlR9YjBP=&I$rCdCf4dm=sMlSfyf2OkN8)6{d+io15}crazi$ zf=b00An>SDaRgfnan8^=a!eHbmLKh@AoW;-yN2dL9Mz($o<9k;2`q8d1r)+-&U%k!eC=pT{O!I&6}BK^xd zrPNdWvnMQ%rrNDiF(#&`U?PQ7T3!=#nyaFzzEG(c6O$JiP4xc8m6em4qpA4O0pb}G zlUFDvua*ZZo{OeBf{K8HF)?|C!A&ud2Y?#IBX4A!7fp4dO2rt&;-Nn{v^juUNA`kZ zaHi=TwCUI}jMOm3Hf=&ois@7Q(r7jG? z!bmaEI2(Ih02%nNY`z8fUugK277ey|YY&@CtA+XkC!XiUeakzCYn2nvZK|j5@W-=# zzCc~jXT|z9?6+f+ZFrW5`{J|`7tdAV;@DE0s{zm33g~8*ye?>H#J}?@_J=|h^Zm0F z6CWgXRfNKJ`mY8e;p?v|*F?U`HzC4d{1EE&={~F3ms?`?SnRd}hqKshjGmrjv6$tD zMyZgVM&oBuRnmNi+2NT{Qsge;v^HM?(jX<_+p3z7LUW1L3L&;4DuB%w4~&)Jtmjw! zyzHG9Yra$=`vz~u`;ypwrZ&@<^o$$K~a8jv;+!bNayv36VusCoJIMCPL*pE zVo1l;;n#f=%3M-XP~e&2%Gb-R%vAynG9WnStFc!Mof!& z7+bZVB2b^xR;=`Cx$UNHD^{jWo~xlQ2}Pn5>Z6JV9cUawN{vNdr7?U^F=x``36t}p z?#_+>#)|&{8T40|`a?~%VHGp0F%b5Xs#$F;D;m`IeWVM6rBBxnd&{OE+=s zc&!W-fiS$Z7q9Hs`rVcE9~V`OwW7YtU+Zj8m!crm3BlX1#PehI`NTrmvt zBu90f+J=zdA;)X2pvgXBVGu~gNeVG!(H2I_Lfb8dnLT}XAx?UHY@Fb@Xia9!Ml&&fg0x)tE%fM{?Q!zsW8);pMUzbVsElA>Inuh1*)veCN0U$sc} zXpF2)L0iD)hvhUZQyl@-jPDgT!ACFiRpEaW1ZYwl<&YvZK3NnG zrM!7u8K4}{3~b{#XJ8v!-N2S;+3E&%wABqvL#rFO=ngaxQ3D!wqBCoPX7*aig|U~A I43Yl-0Za>0A^-pY diff --git a/Source/Core/Common/Src/Log.h b/Source/Core/Common/Src/Log.h index 7383e56c92..9664387cf0 100644 --- a/Source/Core/Common/Src/Log.h +++ b/Source/Core/Common/Src/Log.h @@ -101,7 +101,7 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, #define MAX_LOGLEVEL DEBUG_LEVEL #else #ifndef MAX_LOGLEVEL -#define MAX_LOGLEVEL WARNING_LEVEL +#define MAX_LOGLEVEL DEBUG_LEVEL #endif // loglevel #endif // logging diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index 4d3c7ff8e8..fb75386a4a 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -21,31 +21,29 @@ #include "WII_IPC_HLE.h" #include "WII_IPC_HLE_Device_hid.h" #include "lusb0_usb.h" -#include "hidapi.h" - -static std::map loaded_devices; -static std::map loaded_devices_rev; -static std::map opened_devices; - - +#include "errno.h" CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) { - //usb_init(); /* initialize the library */ - hid_init(); + usb_init(); /* initialize the library */ + } CWII_IPC_HLE_Device_hid::~CWII_IPC_HLE_Device_hid() { - hid_exit(); + for ( std::map::const_iterator iter = open_devices.begin(); iter != open_devices.end(); ++iter ) + { + usb_close(iter->second); + } + open_devices.clear(); } bool CWII_IPC_HLE_Device_hid::Open(u32 _CommandAddress, u32 _Mode) { - Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING); DEBUG_LOG(WII_IPC_HID, "HID::Open"); + m_Active = true; Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); return true; } @@ -53,11 +51,48 @@ bool CWII_IPC_HLE_Device_hid::Open(u32 _CommandAddress, u32 _Mode) bool CWII_IPC_HLE_Device_hid::Close(u32 _CommandAddress, bool _bForce) { DEBUG_LOG(WII_IPC_HID, "HID::Close"); + m_Active = false; if (!_bForce) Memory::Write_U32(0, _CommandAddress + 4); return true; } +u32 CWII_IPC_HLE_Device_hid::Update() +{ + u32 work_done = 0; + int ret = -4; + + std::list<_hidevent>::iterator ev = event_list.begin(); + while (ev != event_list.end()) { + + bool ev_finished = false; + + + switch (ev->type) + { + case IOCTL_HID_INTERRUPT_OUT: + case IOCTL_HID_INTERRUPT_IN: + { + ret = usb_reap_async_nocancel(ev->context, 0); + if(ret >= 0) + { + Memory::Write_U32(ret, ev->enq_address + 4); + WII_IPC_HLE_Interface::EnqReply(ev->enq_address); + work_done = ev_finished = true; + } + + break; + } + } + + if (ev_finished) + event_list.erase(ev++); + else + ev++; + } + return work_done; +} + bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) { static u32 replyAddress = 0; @@ -75,6 +110,7 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) { DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn, BufferInSize, BufferOut, BufferOutSize); + //Memory::Write_U32(0xFFFFFFFF, BufferOut); if(!hasRun) { FillOutDevices(BufferOut, BufferOutSize); @@ -133,7 +169,6 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) ERROR CODES: -4 Cant find device specified */ - u32 dev_num = Memory::Read_U32(BufferIn+0x10); u8 requesttype = Memory::Read_U8(BufferIn+0x14); u8 request = Memory::Read_U8(BufferIn+0x15); @@ -142,11 +177,8 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) u16 size = Memory::Read_U16(BufferIn+0x1A); u32 data = Memory::Read_U32(BufferIn+0x1C); - /* //libusb way - static int upto = 0; - int i; - usb_find_busses(); - usb_find_devices(); + usb_find_busses(); /* find all busses */ + usb_find_devices(); /* find all connected devices */ struct usb_dev_handle * dev_handle = GetDeviceByDevNum(dev_num); @@ -155,7 +187,7 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) ReturnValue = -4; break; } - + ReturnValue = usb_control_msg(dev_handle, requesttype, request, value, index, (char*)Memory::GetPointer(data), size, 0); @@ -164,113 +196,68 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) { ReturnValue += sizeof(usb_ctrl_setup); } - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) = %d", - requesttype, request, ReturnValue); + DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + requesttype, request, ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); - usb_close(dev_handle); - - u8 test_out[0x20]; - Memory::ReadBigEData(test_out, BufferIn, BufferInSize); - char file[0x50]; - snprintf(file, 0x50, "ctrl_ctrlprotocol_%d.bin", upto); - FILE* test = fopen (file, "wb"); - for(i=0;i<0x20;i++) - fwrite(&test_out[i], 1, 1, test); - if (size > 0) - fwrite((char*)Memory::GetPointer(data), 1, size, test); - fclose(test); - upto++; - */ - - hid_device * dev_handle = GetDeviceByDevNumHidLib(dev_num); - - if (dev_handle == NULL) - { - ReturnValue = -4; - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) = %d", - requesttype, request, ReturnValue); - break; - } - - // this is our write request - if(request == 0x09) - { - #define rw_buf_size 0x21 - unsigned char buf[rw_buf_size]; - memset(&buf[0], 0, rw_buf_size); - memcpy(&buf[1], (unsigned char*)Memory::GetPointer(data), size); - int success = hid_write_report(dev_handle, buf, size+1); - - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control) success = %d", success); - } - - ReturnValue = size + sizeof(usb_ctrl_setup); - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) = %d", - requesttype, request, ReturnValue); - - - break; - } - case IOCTL_HID_INTERRUPT_IN: - { - - - u32 dev_num = Memory::Read_U32(BufferIn+0x10); - u32 end_point = Memory::Read_U32(BufferIn+0x14); - u32 length = Memory::Read_U32(BufferIn+0x18); - - u32 data = Memory::Read_U32(BufferIn+0x1C); - - hid_device * dev_handle = GetDeviceByDevNumHidLib(dev_num); - - if (dev_handle == NULL) - { - ReturnValue = -4; - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt In)(%d,%d,%p) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - end_point, length, data, ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); - break; - } - - //ReturnValue = -5; - ReturnValue = hid_read(dev_handle, (unsigned char*)Memory::GetPointer(data), length); - //ReturnValue = usb_interrupt_read(dev_handle, end_point, (char*)Memory::GetPointer(data), length, 1000); - - - FILE* test = fopen ("readdata.bin", "wb"); - fwrite(Memory::GetPointer(data), ReturnValue, 1, test); - fclose(test); - - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt In)(%d,%d,%p) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - end_point, length, data, ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); - break; } case IOCTL_HID_INTERRUPT_OUT: + case IOCTL_HID_INTERRUPT_IN: { + u32 dev_num = Memory::Read_U32(BufferIn+0x10); u32 end_point = Memory::Read_U32(BufferIn+0x14); u32 length = Memory::Read_U32(BufferIn+0x18); u32 data = Memory::Read_U32(BufferIn+0x1C); - - hid_device * dev_handle = GetDeviceByDevNumHidLib(dev_num); + int ret = 0; + void * context = NULL; + + struct usb_dev_handle * dev_handle = GetDeviceByDevNum(dev_num); if (dev_handle == NULL) { ReturnValue = -4; - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt Out) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); - break; + goto int_in_end_print; } - ReturnValue = -5; - //ReturnValue = usb_interrupt_write(dev_handle, end_point, (char*)Memory::GetPointer(data), length, 0); - - DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt Out) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); + usb_claim_interface(dev_handle,0); + + ret = usb_interrupt_setup_async(dev_handle, &context, end_point); + if (ret< 0) + { + ReturnValue = -4; + goto int_in_end_print; + } + ret = usb_submit_async(context, (char*)Memory::GetPointer(data), length); + if (ret< 0) + { + ReturnValue = -4; + goto int_in_end_print; + } + + ret = usb_reap_async_nocancel(context, 0); + if (ret >= 0) + { + ReturnValue = ret; + } + else + { + _hidevent ev; + ev.enq_address = _CommandAddress; + ev.type = Parameter; + ev.context = context; + event_list.push_back(ev); + return false; + } + + int_in_end_print: + DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%p) = %d (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", end_point, length, data, ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize); + break; } @@ -294,16 +281,24 @@ bool CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress) u32 ReturnValue = 0; SIOCtlVBuffer CommandBuffer(_CommandAddress); - DEBUG_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str()); - DEBUG_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter); - DEBUG_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); - DEBUG_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); - DEBUG_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector); - DEBUG_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address); - DEBUG_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size); - #if defined(_DEBUG) || defined(DEBUGFAST) - DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); - #endif + switch (CommandBuffer.Parameter) + { + + default: + { + DEBUG_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str()); + DEBUG_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter); + DEBUG_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer); + DEBUG_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer); + DEBUG_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector); + DEBUG_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address); + DEBUG_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size); + #if defined(_DEBUG) || defined(DEBUGFAST) + DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer, CommandBuffer.NumberPayloadBuffer); + #endif + } + break; + } Memory::Write_U32(ReturnValue, _CommandAddress + 4); return true; @@ -337,137 +332,15 @@ void CWII_IPC_HLE_Device_hid::ConvertEndpointToWii(WiiHIDEndpointDescriptor *des dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize); } -static int x = 0; -u32 CWII_IPC_HLE_Device_hid::GetAvailableID(char* path) -{ - std::string dev_path = path; - if(loaded_devices.find(dev_path) == loaded_devices.end()){ - loaded_devices_rev[x] = dev_path; - loaded_devices[dev_path] = x++; - } - return loaded_devices[dev_path]; -} - -// hidapi version -void CWII_IPC_HLE_Device_hid::FillOutDevicesHidApi(u32 BufferOut, u32 BufferOutSize) -{ - x = 0; - // Enumerate and print the HID devices on the system - struct hid_device_info *devs, *cur_dev; - - int OffsetBuffer = BufferOut; - int OffsetStart = 0; - int c,i,e; // config, interface container, interface, endpoint - - devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; - while (cur_dev) { - - OffsetStart = OffsetBuffer; - OffsetBuffer += 4; // skip length for now, fill at end - - Memory::Write_U32(GetAvailableID(cur_dev->path), OffsetBuffer); //write device num - OffsetBuffer += 4; - - WiiHIDDeviceDescriptor wii_device; - - wii_device.bLength = Common::swap8(0x12); - wii_device.bDescriptorType = Common::swap8(0x1); - wii_device.bcdUSB = Common::swap16(0x0200); - wii_device.bDeviceClass = Common::swap8(0); - wii_device.bDeviceSubClass = Common::swap8(0); - wii_device.bDeviceProtocol = Common::swap8(0); - wii_device.bMaxPacketSize0 = Common::swap8(0x20); - wii_device.idVendor = Common::swap16(cur_dev->vendor_id); - wii_device.idProduct = Common::swap16(cur_dev->product_id); - wii_device.bcdDevice = Common::swap16(cur_dev->release_number); - wii_device.iManufacturer = Common::swap8(0x1); - wii_device.iProduct = Common::swap8(0x2); - wii_device.iSerialNumber = Common::swap8(0); - wii_device.bNumConfigurations = Common::swap8(0x1); - - Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4)); - - OffsetBuffer += Align(wii_device.bLength, 4); - - - for (c = 0; c < Common::swap8(wii_device.bNumConfigurations); c++) - { - - WiiHIDConfigDescriptor wii_config; - wii_config.bLength = Common::swap8(0x9); - wii_config.bDescriptorType = Common::swap8(0x2); - wii_config.wTotalLength = Common::swap16(0x29); - wii_config.bNumInterfaces = Common::swap8(0x1); - wii_config.bConfigurationValue = Common::swap8(0x1); - wii_config.iConfiguration = Common::swap8(0); - wii_config.bmAttributes = Common::swap8(0x80); - wii_config.MaxPower = Common::swap8(0x96); - - Memory::WriteBigEData((const u8*)&wii_config, OffsetBuffer, Align(Common::swap8(wii_config.bLength), 4)); - OffsetBuffer += Align(Common::swap8(wii_config.bLength), 4); - - for (i = 0; i < wii_config.bNumInterfaces; i++) - { - WiiHIDInterfaceDescriptor wii_interface; - - wii_interface.bLength = Common::swap8(0x9); - wii_interface.bDescriptorType = Common::swap8(0x4); - wii_interface.bInterfaceNumber = Common::swap8(i); - wii_interface.bAlternateSetting = Common::swap8(0); - wii_interface.bNumEndpoints = Common::swap8(0x2); - wii_interface.bInterfaceClass = Common::swap8(0x3); - wii_interface.bInterfaceSubClass = Common::swap8(0); - wii_interface.bInterfaceProtocol = Common::swap8(0); - wii_interface.iInterface = Common::swap8(0); - - Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(Common::swap8(wii_interface.bLength), 4)); - OffsetBuffer += Align(Common::swap8(wii_interface.bLength), 4); - - for (e = 0; e < Common::swap8(wii_interface.bNumEndpoints); e++) - { - WiiHIDEndpointDescriptor wii_endpoint; - wii_endpoint.bLength = Common::swap8(0x7); - wii_endpoint.bDescriptorType = Common::swap8(0x5); - wii_endpoint.bEndpointAddress = Common::swap8(e == 0 ? 0x1 : 0x81); - wii_endpoint.bmAttributes = Common::swap8(0x3); - wii_endpoint.wMaxPacketSize = Common::swap16(0x20); - wii_endpoint.bInterval = Common::swap8(0x1); - - Memory::WriteBigEData((const u8*)&wii_endpoint, OffsetBuffer, Align(Common::swap8(wii_endpoint.bLength), 4)); - OffsetBuffer += Align(Common::swap8(wii_endpoint.bLength), 4); - - } //endpoints - } // interfaces - } // configs - - Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length - - NOTICE_LOG(WII_IPC_HID, "Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", - cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number); - NOTICE_LOG(WII_IPC_HID, "\n"); - NOTICE_LOG(WII_IPC_HID, " Manufacturer: %ls\n", cur_dev->manufacturer_string); - NOTICE_LOG(WII_IPC_HID, " Product: %ls\n", cur_dev->product_string); - NOTICE_LOG(WII_IPC_HID, "\n"); - cur_dev = cur_dev->next; - } - Memory::Write_U32(0xFFFFFFFF, OffsetBuffer); // no more devices - - hid_free_enumeration(devs); -} - - -// libusb version void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) { - FillOutDevicesHidApi(BufferOut, BufferOutSize); - /*usb_find_busses(); // find all busses - usb_find_devices(); // find all connected devices + usb_find_busses(); /* find all busses */ + usb_find_devices(); /* find all connected devices */ struct usb_bus *bus; struct usb_device *dev; int OffsetBuffer = BufferOut; int OffsetStart = 0; - int c,ic,i,e; // config, interface container, interface, endpoint + int c,ic,i,e; /* config, interface container, interface, endpoint */ for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) @@ -527,38 +400,34 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) } // buses Memory::Write_U32(0xFFFFFFFF, OffsetBuffer); // no more devices - */ + } - - int CWII_IPC_HLE_Device_hid::Align(int num, int alignment) { return (num + (alignment-1)) & ~(alignment-1); } -hid_device * CWII_IPC_HLE_Device_hid::GetDeviceByDevNumHidLib(u32 devNum) -{ - if (loaded_devices_rev.find(devNum) == loaded_devices_rev.end()) - return NULL; - if (opened_devices.find(devNum) != opened_devices.end()) - return opened_devices[devNum]; - - hid_device * phPortalHandle = opened_devices[devNum] = hid_open_path(loaded_devices_rev[devNum].c_str()); - return phPortalHandle; -} struct usb_dev_handle * CWII_IPC_HLE_Device_hid::GetDeviceByDevNum(u32 devNum) { + + if (open_devices.find(devNum) != open_devices.end()) + return open_devices[devNum]; + + usb_dev_handle * device = NULL; + for (struct usb_bus *bus = usb_get_busses(); bus; bus = bus->next) { for (struct usb_device *dev = bus->devices; dev; dev = dev->next) { if(dev->devnum == devNum){ - return usb_open(dev); + open_devices[devNum] = device = usb_open(dev); + + return device; } } } - return NULL; + return device; } \ No newline at end of file diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.h index 2fc4ba9a22..099f4deff4 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.h @@ -19,7 +19,9 @@ #include "WII_IPC_HLE.h" #include "WII_IPC_HLE_Device.h" -#include "hidapi.h" +#include + +/* Connection timed out */ #define ETRANSFER_TIMEDOUT -116 class CWII_IPC_HLE_Device_hid : public IWII_IPC_HLE_Device { @@ -30,13 +32,12 @@ public: virtual bool Open(u32 _CommandAddress, u32 _Mode); virtual bool Close(u32 _CommandAddress, bool _bForce); + virtual u32 Update(); virtual bool IOCtlV(u32 _CommandAddress); virtual bool IOCtl(u32 _CommandAddress); private: - - std::map deviceList; enum { @@ -112,10 +113,7 @@ private: } WiiHIDEndpointDescriptor; - u32 GetAvailableID(char* path); - - void FillOutDevices(u32 BufferOut, u32 BufferOutSize); - void FillOutDevicesHidApi(u32 BufferOut, u32 BufferOutSize); + void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize); void ConvertDeviceToWii(WiiHIDDeviceDescriptor *dest, struct usb_device_descriptor *src); void ConvertConfigToWii(WiiHIDConfigDescriptor *dest, struct usb_config_descriptor *src); @@ -123,8 +121,17 @@ private: void ConvertEndpointToWii(WiiHIDEndpointDescriptor *dest, struct usb_endpoint_descriptor *src); int Align(int num, int alignment); - hid_device * GetDeviceByDevNumHidLib(u32 devNum); + struct usb_dev_handle * GetDeviceByDevNum(u32 devNum); + std::map open_devices; - + + typedef struct + { + u32 enq_address; + u32 type; + void * context; + } _hidevent; + + std::list<_hidevent> event_list; }; diff --git a/Source/VSProps/Dolphin.x64.props b/Source/VSProps/Dolphin.x64.props index c9cc2eb7ff..fd692daa60 100644 --- a/Source/VSProps/Dolphin.x64.props +++ b/Source/VSProps/Dolphin.x64.props @@ -9,7 +9,7 @@ ..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg64;..\..\..\Externals\portaudio\$(PlatformName)\$(ConfigurationName);..\..\..\Externals\libusb\$(PlatformName) - portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libusb.lib;hidapi.lib;%(AdditionalDependencies) + portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;libusb.lib;%(AdditionalDependencies)