diff --git a/ComboJack_Installer/ComboJack b/ComboJack_Installer/ComboJack new file mode 100644 index 0000000..d73d94f Binary files /dev/null and b/ComboJack_Installer/ComboJack differ diff --git a/ComboJack_Installer/Headphone.icns b/ComboJack_Installer/Headphone.icns new file mode 100644 index 0000000..5d66d7b Binary files /dev/null and b/ComboJack_Installer/Headphone.icns differ diff --git a/ComboJack_Installer/Information.rtf b/ComboJack_Installer/Information.rtf new file mode 100644 index 0000000..73716bc --- /dev/null +++ b/ComboJack_Installer/Information.rtf @@ -0,0 +1,20 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Verdana;} +{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;\red17\green90\blue209; +} +{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c100000;\cssrgb\c5882\c44706\c85490; +} +\margl1440\margr1440\vieww10800\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 + +\f0\fs24 \cf0 Modified ComboJack binary for ALC295 Dell Inspiron 7590/7591 by SaintNo\ +\ +Based on the idea of +\f1 \cf2 \cb3 \expnd0\expndtw0\kerning0 +\'a0{\field{\*\fldinst{HYPERLINK "https://github.com/goodwin/ALCPlugFix"}}{\fldrslt \cf4 \ul \ulc4 https://github.com/goodwin/ALCPlugFix}}\ +Implemented by way of porting hda-verb from alsa-tools:\ +{\field{\*\fldinst{HYPERLINK "https://www.alsa-project.org/main/index.php/Main_Page"}}{\fldrslt https://www.alsa-project.org/main/index.php/Main_Page}}\ +\ +Portions of code adapted from CodecCommander ({\field{\*\fldinst{HYPERLINK "https://github.com/RehabMan/EAPD-Codec-Commander"}}{\fldrslt https://github.com/RehabMan/EAPD-Codec-Commander}}) and the Linux kernel ({\field{\*\fldinst{HYPERLINK "https://github.com/torvalds/linux"}}{\fldrslt https://github.com/torvalds/linux}}). All copyrights belong to their respective owners.\ +\ +Uses layout-id 77. VerbStub.kext goes into EFI/Clover/kexts/Other.} \ No newline at end of file diff --git a/ComboJack_Installer/LICENSE b/ComboJack_Installer/LICENSE new file mode 100644 index 0000000..c8ee2c2 --- /dev/null +++ b/ComboJack_Installer/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + handles EAPD state updating for power-managed HDA codecs + Copyright (C) 2013 Dolnor + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ComboJack_Installer/VerbStub.kext/Contents/Info.plist b/ComboJack_Installer/VerbStub.kext/Contents/Info.plist new file mode 100644 index 0000000..43bc920 --- /dev/null +++ b/ComboJack_Installer/VerbStub.kext/Contents/Info.plist @@ -0,0 +1,84 @@ + + + + + BuildMachineOSBuild + 20D91 + CFBundleDevelopmentRegion + en + CFBundleExecutable + VerbStub + CFBundleIdentifier + com.XPS.VerbStub + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + VerbStub + CFBundlePackageType + KEXT + CFBundleShortVersionString + 1.0.4 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1.0.4 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 12D4e + DTPlatformName + macosx + DTPlatformVersion + 11.1 + DTSDKBuild + 20C63 + DTSDKName + macosx11.1 + DTXcode + 1240 + DTXcodeBuild + 12D4e + IOKitPersonalities + + VerbStub + + CFBundleIdentifier + com.XPS.VerbStub + IOClass + com_XPS_VerbStub + IOMatchCategory + com_XPS_VerbStub + IOProviderClass + IOHDACodecFunction + IOUserClientClass + VerbStubUserClient + + VerbStubResidency + + CFBundleIdentifier + com.XPS.VerbStub + IOClass + VerbStubResidency + IOMatchCategory + VerbStubResidency + IOProviderClass + IOResources + + + LSMinimumSystemVersion + 10.12 + NSHumanReadableCopyright + Copyright © 2017 VerbStub. All rights reserved. + OSBundleLibraries + + com.apple.iokit.IOPCIFamily + 2.9 + com.apple.kpi.iokit + 16.6 + com.apple.kpi.libkern + 16.6 + + + diff --git a/ComboJack_Installer/VerbStub.kext/Contents/MacOS/VerbStub b/ComboJack_Installer/VerbStub.kext/Contents/MacOS/VerbStub new file mode 100644 index 0000000..949dd41 Binary files /dev/null and b/ComboJack_Installer/VerbStub.kext/Contents/MacOS/VerbStub differ diff --git a/ComboJack_Installer/com.XPS.ComboJack.plist b/ComboJack_Installer/com.XPS.ComboJack.plist new file mode 100644 index 0000000..3973c23 --- /dev/null +++ b/ComboJack_Installer/com.XPS.ComboJack.plist @@ -0,0 +1,18 @@ + + + + + KeepAlive + + Label + com.XPS.ComboJack + ProgramArguments + + /usr/local/sbin/ComboJack + + RunAtLoad + + ServiceIPC + + + diff --git a/ComboJack_Installer/hda-verb b/ComboJack_Installer/hda-verb new file mode 100644 index 0000000..fcadb50 Binary files /dev/null and b/ComboJack_Installer/hda-verb differ diff --git a/ComboJack_Installer/install.sh b/ComboJack_Installer/install.sh new file mode 100644 index 0000000..105fc4e --- /dev/null +++ b/ComboJack_Installer/install.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +if [[ $EUID -ne 0 ]]; +then + exec sudo /bin/bash "$0" "$@" +fi + +cd "$( dirname "${BASH_SOURCE[0]}" )" + +# Clean legacy stuff +# +sudo launchctl unload /Library/LaunchDaemons/com.XPS.ComboJack.plist 2>/dev/null +sudo rm -rf /Library/Extensions/CodecCommander.kext +sudo rm -f /usr/local/bin/ALCPlugFix +sudo rm -f /Library/LaunchAgents/good.win.ALCPlugFix +sudo rm -f /Library/LaunchDaemons/good.win.ALCPlugFix +sudo rm -f /usr/local/sbin/hda-verb +sudo rm -f /usr/local/share/ComboJack/Headphone.icns +sudo rm -f /usr/local/share/ComboJack/l10n.json + +# install +sudo mkdir -p /usr/local/sbin +sudo cp ComboJack /usr/local/sbin +sudo chmod 755 /usr/local/sbin/ComboJack +sudo chown root:wheel /usr/local/sbin/ComboJack +sudo cp hda-verb /usr/local/sbin +#sudo chmod 755 /usr/local/sbin/hda-verb +#sudo chown root:wheel /usr/local/sbin/hda-verb +sudo mkdir -p /usr/local/share/ComboJack/ +sudo cp Headphone.icns /usr/local/share/ComboJack/ +sudo chmod 644 /usr/local/share/ComboJack/Headphone.icns +sudo cp l10n.json /usr/local/share/ComboJack/ +sudo chmod 644 /usr/local/share/ComboJack/l10n.json +sudo cp com.XPS.ComboJack.plist /Library/LaunchDaemons/ +sudo chmod 644 /Library/LaunchDaemons/com.XPS.ComboJack.plist +sudo chown root:wheel /Library/LaunchDaemons/com.XPS.ComboJack.plist +sudo launchctl load /Library/LaunchDaemons/com.XPS.ComboJack.plist +echo +echo "Install successfully!" +echo "Please reboot! Also, it may be a good idea to turn off \"Use" +echo "ambient noise reduction\" when using an input method other than" +echo "the internal mic (meaning line-in, headset mic). As always: YMMV." +echo +echo "You can check to see if the watcher is working in the IORegistry:" +echo "there should be a device named \"VerbStubUserClient\" attached to" +echo "\"com_XPS_SetVerb\" somewhere within the \"HDEF\" entry's hierarchy." +echo +echo "Enjoy!" +echo +exit 0 \ No newline at end of file diff --git a/ComboJack_Installer/l10n.json b/ComboJack_Installer/l10n.json new file mode 100644 index 0000000..a5f6eaf --- /dev/null +++ b/ComboJack_Installer/l10n.json @@ -0,0 +1,26 @@ +{ + "zh_CN": { + "dialogTitle" : "耳机接入通知", + "dialogMsg" : "请选择接入的设备类型(按ESC键取消)", + "btnHeadphone" : "耳机", + "btnLinein" : "线路输入", + "btnHeadset" : "耳麦", + "btnCancel" : "取消" + }, + "en_US": { + "dialogTitle" : "Combo Jack Selection", + "dialogMsg" : "Select your device type (Press ESC to cancel)", + "btnHeadphone" : "Headphones", + "btnLinein" : "Line-In", + "btnHeadset" : "Headset", + "btnCancel" : "Cancel" + }, + "vi_VN": { + "dialogTitle" : "Thông báo cắm tai nghe", + "dialogMsg" : "Lựa chọn loại thiết bị được cắm vào? (Bấm ESC để huỷ)", + "btnHeadphone" : "Tai nghe thường", + "btnLinein" : "Microphone", + "btnHeadset" : "Tai nghe có mic", + "btnCancel" : "Huỷ" + } +} diff --git a/ComboJack_Source/Combo Jack/PCI.h b/ComboJack_Source/Combo Jack/PCI.h new file mode 100644 index 0000000..1c2e8c5 --- /dev/null +++ b/ComboJack_Source/Combo Jack/PCI.h @@ -0,0 +1,71 @@ +// +// pci.h +// DPCIManager +// +// Created by PHPdev32 on 10/8/12. +// Licensed under GPLv3, full text at http://www.gnu.org/licenses/gpl-3.0.txt +// + +#import +#import + +@interface pciDevice : NSObject + +@property uint64_t entryID; +@property NSNumber *shadowVendor; +@property NSNumber *shadowDevice; +@property NSNumber *revision; +@property NSArray *bus; +@property NSNumber *vendor; +@property NSNumber *device; +@property NSNumber *subVendor; +@property NSNumber *subDevice; +@property NSNumber *pciClassCode; +@property NSNumber *pciClass; +@property NSNumber *pciSubClass; +@property NSString *vendorString; +@property NSString *deviceString; +@property NSString *classString; +@property NSString *subClassString; +@property (readonly) NSString *fullClassString; +@property (readonly) NSString *lspciString; +@property (readonly) NSDictionary *lspciDictionary; +@property (readonly) long fullID; +@property (readonly) long fullSubID; +@property (readonly) short bdf; + ++(long)nameToLong:(NSString *)name; ++(bool)isPCI:(io_service_t)service; ++(NSNumber *)grabNumber:(CFStringRef)entry forService:(io_service_t)service; ++(NSString *)grabString:(CFStringRef)entry forService:(io_service_t)service; ++(NSDictionary *)match:(pciDevice *)pci; ++(pciDevice *)create:(io_service_t)service classes:(NSMutableDictionary *)classes vendors:(NSMutableDictionary *)vendors; ++(pciDevice *)create:(io_service_t)service; ++(NSArray *)readIDs; + +@end + +@interface pciVendor : NSObject +@property NSString *name; +@property NSMutableDictionary *devices; ++(pciVendor *)create:(NSString *)name; +@end + +@interface pciClass : NSObject +@property NSString *name; +@property NSMutableDictionary *subClasses; ++(pciClass *)create:(NSString *)name; +@end + +@interface efiObject : NSObject +@property NSDictionary *properties; +@property pciDevice *device; ++(efiObject *)create:(pciDevice *)device injecting:(NSDictionary *)properties; ++(NSString *)stringWithArray:(NSArray *)array; +@end + +@interface hexFormatter : NSValueTransformer ++(BOOL)allowsReverseTransformation; ++(Class)transformedValueClass; +-(id)transformedValue:(id)value; +@end diff --git a/ComboJack_Source/Combo Jack/PCI.m b/ComboJack_Source/Combo Jack/PCI.m new file mode 100644 index 0000000..fe16c64 --- /dev/null +++ b/ComboJack_Source/Combo Jack/PCI.m @@ -0,0 +1,339 @@ +// +// pci.m +// DPCIManager +// +// Created by PHPdev32 on 10/8/12. +// Licensed under GPLv3, full text at http://www.gnu.org/licenses/gpl-3.0.txt +// + +#import "PCI.h" +#import "Tables.h" +#define h64tob32(x) (unsigned)(CFSwapInt64HostToBig(x)>>32) +#define strHexDec(x) strtol([x UTF8String], NULL, 16) + +#pragma mark Device Class +@implementation pciDevice + +@synthesize vendor; +@synthesize device; +@synthesize subVendor; +@synthesize subDevice; +@synthesize pciClassCode; +@synthesize pciClass; +@synthesize pciSubClass; +@synthesize bus; +@synthesize revision; +@synthesize shadowDevice; +@synthesize shadowVendor; +@synthesize vendorString; +@synthesize deviceString; +@synthesize classString; +@synthesize subClassString; + ++(long)nameToLong:(NSString *)name{ + if (![name hasPrefix:@"pci"] || [name rangeOfString:@","].location == NSNotFound) return 0; + NSArray *temp = [[name stringByReplacingOccurrencesOfString:@"pci" withString:@""] componentsSeparatedByString:@","]; + return strHexDec([temp objectAtIndex:1]) << 16 | strHexDec([temp objectAtIndex:0]); +} ++(bool)isPCI:(io_service_t)service{ + return [@"IOPCIDevice" isEqualToString:(__bridge_transfer NSString *)IOObjectCopyClass(service)]; +} ++(NSNumber *)grabNumber:(CFStringRef)entry forService:(io_service_t)service{//FIXME: shift bridge + id number = (__bridge_transfer id)IORegistryEntryCreateCFProperty(service, entry, kCFAllocatorDefault, 0); + NSNumber *temp = @0; + if (!number) return temp; + if ([number isKindOfClass:[NSNumber class]]) return number; + else if ([number isKindOfClass:[NSData class]]) + temp = @(*(NSInteger *)[number bytes]); + return temp; +} ++(NSString *)grabString:(CFStringRef)entry forService:(io_service_t)service{ + id string = (__bridge_transfer id)IORegistryEntryCreateCFProperty(service, entry, kCFAllocatorDefault, 0); + NSString *temp = @""; + if (!string) return temp; + if ([string isKindOfClass:[NSString class]]) return string; + else if ([string isKindOfClass:[NSData class]]) + if (!(temp = [[NSString alloc] initWithData:string encoding:NSUTF8StringEncoding])) + temp = [[NSString alloc] initWithData:string encoding:NSASCIIStringEncoding]; + return temp; +} ++(NSDictionary *)match:(pciDevice *)pci{ + NSInteger vendor = pci.vendor.integerValue; + NSInteger device = pci.device.integerValue; + return @{@kIOPropertyMatchKey:@{@"vendor-id":[NSData dataWithBytes:&vendor length:4], @"device-id":[NSData dataWithBytes:&device length:4]}}; +} ++(pciDevice *)create:(io_service_t)service classes:(NSMutableDictionary *)classes vendors:(NSMutableDictionary *)vendors{ + pciDevice *temp = [pciDevice create:service]; + temp.vendorString = [[vendors objectForKey:temp.shadowVendor] name]; + temp.deviceString = [[[vendors objectForKey:temp.shadowVendor] devices] objectForKey:temp.shadowDevice]; + temp.classString = [[classes objectForKey:temp.pciClass] name]; + temp.subClassString = [[[classes objectForKey:temp.pciClass] subClasses] objectForKey:temp.pciSubClass]; + return temp; +} ++(pciDevice *)create:(io_service_t)service{//FIXME: add validator option? + pciDevice *temp = [pciDevice new];//!!!: agreements are base&compat, sub&compatsub, IOName&name + @try { + IORegistryEntryGetRegistryEntryID(service, &temp->_entryID); + temp.vendor = [self grabNumber:CFSTR("vendor-id") forService:service]; + temp.device = [self grabNumber:CFSTR("device-id") forService:service]; + temp.bus = [[[[pciDevice grabString:CFSTR("pcidebug") forService:service] stringByReplacingOccurrencesOfString:@"(" withString:@":"] componentsSeparatedByString:@":"] valueForKey:@"integerValue"]; + if (![pciDevice isPCI:service]) [NSException raise:@"notpci" format:@"Not a real pci device!"]; + temp.subVendor = [self grabNumber:CFSTR("subsystem-vendor-id") forService:service]; + temp.subDevice = [self grabNumber:CFSTR("subsystem-id") forService:service]; + temp.pciClassCode = [self grabNumber:CFSTR("class-code") forService:service]; + temp.pciClass = @((temp.pciClassCode.integerValue >> 16) &0xFF); + temp.pciSubClass = @((temp.pciClassCode.integerValue >> 8) &0xFF); + temp.revision = [self grabNumber:CFSTR("revision-id") forService:service]; + long ids = 0; + NSString *string = [pciDevice grabString:CFSTR("IOName") forService:service]; + if (string.length) ids = [self nameToLong:string]; + //else [NSException raise:@"noioname" format:@"Missing IOName"]; + if (!ids) { + string = [pciDevice grabString:CFSTR("name") forService:service]; + if (string.length) ids = [self nameToLong:string]; + //else [NSException raise:@"noioname" format:@"Missing name"]; + } + temp.shadowVendor = !ids?temp.vendor:@(ids & 0xFFFF); + temp.shadowDevice = !ids?temp.device:@(ids >> 16); + } + @catch (NSException *e) { + //NSRunCriticalAlertPanel(@"PCI Error", @"%@ 0x%04X%04X", nil, nil, nil, e.reason, temp.vendor.intValue, temp.device.intValue); + temp.vendor = temp.device = temp.subVendor = temp.subDevice = temp.pciClassCode = temp.pciClass = temp.pciSubClass = temp.revision = temp.shadowVendor = temp.shadowDevice = @0; + temp.bus = @[temp.vendor, temp.vendor, temp.vendor]; + } + @finally { + return temp; + } +} +-(NSString *)fullClassString{ + return [NSString stringWithFormat:@"%@, %@", classString, subClassString]; +} +-(NSString *)lspciString{ + return [NSString stringWithFormat:@"%02lx:%02lx.%01lx %@ [%04lx]: %@ %@ [%04lx:%04lx]%@%@", [[bus objectAtIndex:0] integerValue], [[bus objectAtIndex:1] integerValue], [[bus objectAtIndex:2] integerValue], subClassString, pciClassCode.integerValue>>8, vendorString, deviceString, shadowVendor.integerValue, shadowDevice.integerValue, !revision.integerValue?@"":[NSString stringWithFormat:@" (rev %02lx)", revision.integerValue], !subDevice.integerValue?@"":[NSString stringWithFormat:@" (subsys %04lx:%04lx)", subVendor.integerValue, subDevice.integerValue]]; +} +-(NSDictionary *)lspciDictionary{ + NSDictionary *lspci_dict = @{ + // BusNumber:DeviceNumber.FunctionNumber + @"BDF": [NSString stringWithFormat:@"%02lx:%02lx.%01lx", [[bus objectAtIndex:0] integerValue], [[bus objectAtIndex:1] integerValue], [[bus objectAtIndex:2] integerValue]], + // Device's Class + @"Class": @{ + @"ClassName": [NSString stringWithFormat:@"%@", classString], + @"SubclassName": [NSString stringWithFormat:@"%@", subClassString], + @"ID": [NSString stringWithFormat:@"%04lx", pciClassCode.integerValue>>8] + }, + // Device Info + @"Info": @{ + @"Name": [NSString stringWithFormat:@"%@", deviceString], + @"Vendor": [NSString stringWithFormat:@"%@", vendorString] + }, + // Device ID + @"ID": @{ + @"DeviceID": [NSString stringWithFormat:@"%04lx", shadowDevice.integerValue], + @"VendorID": [NSString stringWithFormat:@"%04lx", shadowVendor.integerValue] + }, + // Subsystem ID + @"SubsysID": @{ + @"DeviceID": [NSString stringWithFormat:@"%04lx", subDevice.integerValue], + @"VendorID": [NSString stringWithFormat:@"%04lx", subVendor.integerValue] + }, + // Revision + @"Rev": [NSString stringWithFormat:@"%02lx", revision.integerValue] + }; + return lspci_dict; +} +-(long)fullID{ + return device.integerValue<<16 | vendor.integerValue; +} +-(long)fullSubID{ + return subDevice.integerValue<<16 | subVendor.integerValue; +} +-(short)bdf { + if (self.bus.count > 2) + return [[self.bus objectAtIndex:0] unsignedCharValue] << 8 | [[self.bus objectAtIndex:1] unsignedCharValue] << 3 | [[self.bus objectAtIndex:2] unsignedCharValue]; + return -1; +} + ++(NSArray *)readIDs{ + FILE *handle = fopen([[NSBundle.mainBundle pathForResource:@"pci" ofType:@"ids"] fileSystemRepresentation], "rb"); + NSMutableDictionary *classes = [NSMutableDictionary dictionary]; + NSMutableDictionary *vendors = [NSMutableDictionary dictionary]; + NSNumber *currentClass; + NSNumber *currentVendor; + char buffer[LINE_MAX]; + long device_id, subclass_id; + char *buf; + bool class_parse = false; + while((buf = fgets(buffer, LINE_MAX, handle)) != NULL) { + if (buf[0] == '#' || strlen(buf) <= 4) continue; + buf[strlen(buf)-1]='\0'; + if (*buf == 'C') class_parse = true; + if (class_parse) { + if (*buf == '\t') { + buf++; + if (*buf != '\t') { + subclass_id = strtol(buf, NULL, 16); + buf += 4; + while (*buf == ' ' || *buf == '\t') buf++; + [[[classes objectForKey:currentClass] subClasses] setObject:@(buf) forKey:@(subclass_id)]; + } + } + else if (*buf == 'C') { + buf += 2; + currentClass = @(strtol(buf, NULL, 16)); + buf += 4; + while (*buf == ' ' || *buf == '\t') buf++; + [classes setObject:[pciClass create:@(buf)] forKey:currentClass]; + } + } + else { + if (*buf == '\t') { + buf++; + if (*buf != '\t') { + device_id = strtol(buf, NULL, 16); + buf += 4; + while (*buf == ' ' || *buf == '\t') buf++; + [[[vendors objectForKey:currentVendor] devices] setObject:@(buf) forKey:@(device_id)]; + } + } + else if (*buf != '\\') { + currentVendor = @(strtol(buf, NULL, 16)); + buf += 4; + while (*buf == ' ' || *buf == '\t') buf++; + [vendors setObject:[pciVendor create:@(buf)] forKey:currentVendor]; + } + } + } + fclose(handle); + NSMutableArray *pcis = [NSMutableArray array]; + io_iterator_t itThis; + if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOPCIDevice"), &itThis) == KERN_SUCCESS) { + io_service_t service; + while((service = IOIteratorNext(itThis))){ + pciDevice *pci = [pciDevice create:service classes:classes vendors:vendors]; + if (pci.fullID+pci.fullSubID > 0) [pcis addObject:pci]; + IOObjectRelease(service); + } + IOObjectRelease(itThis); + } + return [pcis copy]; +} +@end + +#pragma mark ID Classes +@implementation pciVendor +@synthesize name; +@synthesize devices; ++(pciVendor *)create:(NSString *)name{ + pciVendor *temp = [pciVendor new]; + temp.name = name; + temp.devices = [NSMutableDictionary dictionary]; + return temp; +} +@end + +@implementation pciClass +@synthesize name; +@synthesize subClasses; ++(pciClass *)create:(NSString *)name{ + pciClass *temp = [pciClass new]; + temp.name = name; + temp.subClasses = [NSMutableDictionary dictionary]; + return temp; +} +@end + +@implementation efiObject +@synthesize properties; +@synthesize device; ++(efiObject *)create:(pciDevice *)device injecting:(NSDictionary *)properties{ + efiObject *temp = [efiObject new]; + temp.properties = properties; + temp.device = device; + return temp; +} ++(NSString *)stringWithArray:(NSArray *)array{ + NSMutableString *str = [NSMutableString stringWithFormat:@"%08x%08x", CFSwapInt32HostToBig(1), h64tob32(array.count)]; + for (efiObject *obj in array) { + NSMutableString *efi = [NSMutableString stringWithFormat:@"%08x", 0x7fff0400]; + io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, (__bridge_retained CFDictionaryRef)[pciDevice match:obj.device]); + while (true) { + NSString *property; + if ((property = [pciDevice grabString:CFSTR("pcidebug") forService:service]) && property.length) { + NSArray *bus = [[[property stringByReplacingOccurrencesOfString:@"(" withString:@":"] componentsSeparatedByString:@":"] valueForKey:@"integerValue"]; + [efi insertString:[NSString stringWithFormat:@"%08x%02x%02x", 0x01010600, [[bus objectAtIndex:2] intValue], [[bus objectAtIndex:1] intValue]] atIndex:0]; + } + else if ((property = [pciDevice grabString:CFSTR("name") forService:service]).length) { + unsigned pnp = 0; + sscanf(property.UTF8String, "PNP%X", &pnp); + if (!pnp) { + efi = nil; + break; + } + if (!(property = [pciDevice grabString:CFSTR("_UID") forService:service]).length) property = @"0"; + unsigned uid = property.intValue; + [efi insertString:[NSString stringWithFormat:@"%08x%04x%04x%08x", 0x02010C00, 0xD041, CFSwapInt16HostToBig(pnp), CFSwapInt32HostToBig(uid)] atIndex:0]; + break; + } + io_service_t parent; + IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent); + IOObjectRelease(service); + service = parent; + } + IOObjectRelease(service); + if (!efi) return nil; + for(NSString *property in obj.properties) { + NSUInteger i = 0, j = property.length+1; + [efi appendFormat:@"%08x", h64tob32(4+j*2)]; + const char *prop = property.UTF8String; + while (i>(64-i*8)]; + } + [str appendFormat:@"%08x%08x%@", h64tob32(8+efi.length/2), h64tob32(obj.properties.count), efi]; + } + return [NSString stringWithFormat:@"%08x%@", h64tob32(4+str.length/2), str]; +} ++(int)NumberSize:(NSNumber *)number { + switch (number.objCType[0]) { + case 'c': + return sizeof(char); + case 'i': + return sizeof(int); + case 's': + return sizeof(short); + case 'l': + return sizeof(long); + case 'q': + return sizeof(long long); + case 'f': + return sizeof(float); + case 'd': + return sizeof(double); + case 'C': + return sizeof(unsigned char); + case 'I': + return sizeof(unsigned int); + case 'S': + return sizeof(unsigned short); + case 'L': + return sizeof(unsigned long); + case 'Q': + return sizeof(unsigned long long); + default: + return 0; + } +} +@end + +#pragma mark Formatter +@implementation hexFormatter ++(BOOL)allowsReverseTransformation{ + return false; +} ++(Class)transformedValueClass{ + return [NSString class]; +} +-(id)transformedValue:(id)value{ + return [NSString stringWithFormat:@"%04lX", [(NSNumber *)value integerValue]]; +} +@end diff --git a/ComboJack_Source/Combo Jack/Tables.h b/ComboJack_Source/Combo Jack/Tables.h new file mode 100644 index 0000000..7670c60 --- /dev/null +++ b/ComboJack_Source/Combo Jack/Tables.h @@ -0,0 +1,653 @@ +// +// Tables.h +// DPCIManager +// +// Created by PHPdev32 on 9/16/12. +// + +#ifndef DPCIManager_Tables_h +#define DPCIManager_Tables_h + +#define CODEC_ID(vendor,device) ((((UInt32) vendor & 0xffff) << 16) | \ +((UInt32) device & 0xffff)) + +#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || (fl) == 0xffffffff || \ +(((fl) & 0xffff0000) == 0xffff0000 && ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \ +(((fl) & 0x0000ffff) == 0x0000ffff && ((fl) & 0xffff0000) == ((v) & 0xffff0000))) + +/* All codecs you can eat... */ +#define HDA_CODEC_CONSTRUCT(vendor, id) (((UInt32) (vendor##_VENDORID) << 16) | ((id) & 0xffff)) + +// +// Laptop codecs have a comment "Laptop" beside them, both has "Both" +// + +/* Cirrus Logic */ +#define CIRRUSLOGIC_VENDORID 0x1013 +#define HDA_CODEC_CS4206 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4206) +#define HDA_CODEC_CS4207 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4207) +#define HDA_CODEC_CS4210 HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0x4210) +#define HDA_CODEC_CSXXXX HDA_CODEC_CONSTRUCT(CIRRUSLOGIC, 0xffff) + +/* Realtek */ +#define REALTEK_VENDORID 0x10ec +#define HDA_CODEC_ALC221 HDA_CODEC_CONSTRUCT(REALTEK, 0x0221) +#define HDA_CODEC_ALC230 HDA_CODEC_CONSTRUCT(REALTEK, 0x0230) // new Laptop (rev 0x0002) +#define HDA_CODEC_ALC233 HDA_CODEC_CONSTRUCT(REALTEK, 0x0233) // new Both +#define HDA_CODEC_ALC235 HDA_CODEC_CONSTRUCT(REALTEK, 0x0235) // new Laptop +#define HDA_CODEC_ALC255 HDA_CODEC_CONSTRUCT(REALTEK, 0x0255) // new Laptop (rev 0x0000) +#define HDA_CODEC_ALC256 HDA_CODEC_CONSTRUCT(REALTEK, 0x0256) // new Laptop (rev 0x0002) +#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260) +#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262) +#define HDA_CODEC_ALC267 HDA_CODEC_CONSTRUCT(REALTEK, 0x0267) +#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268) // Both +#define HDA_CODEC_ALC269 HDA_CODEC_CONSTRUCT(REALTEK, 0x0269) // Both +#define HDA_CODEC_ALC270 HDA_CODEC_CONSTRUCT(REALTEK, 0x0270) // Both +#define HDA_CODEC_ALC272 HDA_CODEC_CONSTRUCT(REALTEK, 0x0272) // Both +#define HDA_CODEC_ALC273 HDA_CODEC_CONSTRUCT(REALTEK, 0x0273) +#define HDA_CODEC_ALC275 HDA_CODEC_CONSTRUCT(REALTEK, 0x0275) +#define HDA_CODEC_ALC276 HDA_CODEC_CONSTRUCT(REALTEK, 0x0276) +#define HDA_CODEC_ALC282 HDA_CODEC_CONSTRUCT(REALTEK, 0x0282) // new +#define HDA_CODEC_ALC292 HDA_CODEC_CONSTRUCT(REALTEK, 0x0292) // new +#define HDA_CODEC_ALC295 HDA_CODEC_CONSTRUCT(REALTEK, 0x0295) // new +#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660) +#define HDA_CODEC_ALC662 HDA_CODEC_CONSTRUCT(REALTEK, 0x0662) +#define HDA_CODEC_ALC663 HDA_CODEC_CONSTRUCT(REALTEK, 0x0663) +#define HDA_CODEC_ALC665 HDA_CODEC_CONSTRUCT(REALTEK, 0x0665) +#define HDA_CODEC_ALC670 HDA_CODEC_CONSTRUCT(REALTEK, 0x0670) +#define HDA_CODEC_ALC680 HDA_CODEC_CONSTRUCT(REALTEK, 0x0680) +#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861) +#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862) +#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880) +#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882) +#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883) +#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885) +#define HDA_CODEC_ALC887 HDA_CODEC_CONSTRUCT(REALTEK, 0x0887) +#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888) +#define HDA_CODEC_ALC889 HDA_CODEC_CONSTRUCT(REALTEK, 0x0889) +#define HDA_CODEC_ALC891 HDA_CODEC_CONSTRUCT(REALTEK, 0x0891) // new +#define HDA_CODEC_ALC892 HDA_CODEC_CONSTRUCT(REALTEK, 0x0892) +#define HDA_CODEC_ALC898 HDA_CODEC_CONSTRUCT(REALTEK, 0x0899) +#define HDA_CODEC_ALC899 HDA_CODEC_CONSTRUCT(REALTEK, 0x0899) // new +#define HDA_CODEC_ALC1150 HDA_CODEC_CONSTRUCT(REALTEK, 0x0900) +#define HDA_CODEC_ALCS1220A HDA_CODEC_CONSTRUCT(REALTEK, 0x1168) // new (Asus) +#define HDA_CODEC_ALC1220 HDA_CODEC_CONSTRUCT(REALTEK, 0x1220) // new +#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff) + +/* Motorola */ +#define MOTO_VENDORID 0x1057 +#define HDA_CODEC_MOTOXXXX HDA_CODEC_CONSTRUCT(MOTO, 0xffff) + +/* Creative */ +#define CREATIVE_VENDORID 0x1102 +#define HDA_CODEC_CA0110 HDA_CODEC_CONSTRUCT(CREATIVE, 0x000a) +#define HDA_CODEC_CA0110_2 HDA_CODEC_CONSTRUCT(CREATIVE, 0x000b) +#define HDA_CODEC_SB0880 HDA_CODEC_CONSTRUCT(CREATIVE, 0x000d) +#define HDA_CODEC_CA0132 HDA_CODEC_CONSTRUCT(CREATIVE, 0x0011) +#define HDA_CODEC_CAXXXX HDA_CODEC_CONSTRUCT(CREATIVE, 0xffff) + +/* Analog Devices */ +#define ANALOGDEVICES_VENDORID 0x11d4 +#define HDA_CODEC_AD1884A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a) +#define HDA_CODEC_AD1882 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1882) +#define HDA_CODEC_AD1883 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1883) +#define HDA_CODEC_AD1884 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1884) +#define HDA_CODEC_AD1984A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194a) +#define HDA_CODEC_AD1984B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x194b) +#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981) +#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983) +#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984) +#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986) +#define HDA_CODEC_AD1987 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1987) +#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988) +#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b) +#define HDA_CODEC_AD1882A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x882a) +#define HDA_CODEC_AD1989A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989a) +#define HDA_CODEC_AD1989B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x989b) +#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff) + +/* CMedia */ +#define CMEDIA_VENDORID 0x13f6 +#define HDA_CODEC_CMI9880 HDA_CODEC_CONSTRUCT(CMEDIA, 0x9880) +#define HDA_CODEC_CMIXXXX HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff) + +#define CMEDIA2_VENDORID 0x434d +#define HDA_CODEC_CMI98802 HDA_CODEC_CONSTRUCT(CMEDIA2, 0x4980) +#define HDA_CODEC_CMIXXXX2 HDA_CODEC_CONSTRUCT(CMEDIA2, 0xffff) + +/* Sigmatel */ +#define SIGMATEL_VENDORID 0x8384 +#define HDA_CODEC_STAC9230X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612) +#define HDA_CODEC_STAC9230D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7613) +#define HDA_CODEC_STAC9229X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7614) +#define HDA_CODEC_STAC9229D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7615) +#define HDA_CODEC_STAC9228X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7616) +#define HDA_CODEC_STAC9228D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7617) +#define HDA_CODEC_STAC9227X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618) +#define HDA_CODEC_STAC9227D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7619) +#define HDA_CODEC_STAC9274 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7620) +#define HDA_CODEC_STAC9274D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7621) +#define HDA_CODEC_STAC9273X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7622) +#define HDA_CODEC_STAC9273D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7623) +#define HDA_CODEC_STAC9272X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7624) +#define HDA_CODEC_STAC9272D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7625) +#define HDA_CODEC_STAC9271X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7626) +#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627) +#define HDA_CODEC_STAC9274X5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7628) +#define HDA_CODEC_STAC9274D5NH HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7629) +#define HDA_CODEC_STAC9250 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7634) +#define HDA_CODEC_STAC9251 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7636) +#define HDA_CODEC_IDT92HD700X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7638) +#define HDA_CODEC_IDT92HD700D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7639) +#define HDA_CODEC_IDT92HD206X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7645) +#define HDA_CODEC_IDT92HD206D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7646) +#define HDA_CODEC_CXD9872RDK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7661) +#define HDA_CODEC_STAC9872AK HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7662) +#define HDA_CODEC_CXD9872AKD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7664) +#define HDA_CODEC_STAC9221 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7680) +#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681) +#define HDA_CODEC_STAC9221_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7682) +#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683) +#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690) +#define HDA_CODEC_STAC9200D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7691) +#define HDA_CODEC_IDT92HD005 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7698) +#define HDA_CODEC_IDT92HD005D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7699) +#define HDA_CODEC_STAC9205X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a0) +#define HDA_CODEC_STAC9205D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1) +#define HDA_CODEC_STAC9204X HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2) +#define HDA_CODEC_STAC9204D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3) +#define HDA_CODEC_STAC9255 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a4) +#define HDA_CODEC_STAC9255D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a5) +#define HDA_CODEC_STAC9254 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a6) +#define HDA_CODEC_STAC9254D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a7) +#define HDA_CODEC_STAC9220_A2 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880) +#define HDA_CODEC_STAC9220_A1 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882) +#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff) + +/* IDT */ +#define IDT_VENDORID 0x111d +#define HDA_CODEC_IDT92HD75BX HDA_CODEC_CONSTRUCT(IDT, 0x7603) +#define HDA_CODEC_IDT92HD83C1X HDA_CODEC_CONSTRUCT(IDT, 0x7604) +#define HDA_CODEC_IDT92HD81B1X HDA_CODEC_CONSTRUCT(IDT, 0x7605) +#define HDA_CODEC_IDT92HD75B3 HDA_CODEC_CONSTRUCT(IDT, 0x7608) +#define HDA_CODEC_IDT92HD73D1 HDA_CODEC_CONSTRUCT(IDT, 0x7674) +#define HDA_CODEC_IDT92HD73C1 HDA_CODEC_CONSTRUCT(IDT, 0x7675) +#define HDA_CODEC_IDT92HD73E1 HDA_CODEC_CONSTRUCT(IDT, 0x7676) +#define HDA_CODEC_IDTID7695 HDA_CODEC_CONSTRUCT(IDT, 0x7695) // new +#define HDA_CODEC_IDT92HD71B8 HDA_CODEC_CONSTRUCT(IDT, 0x76b0) +#define HDA_CODEC_IDT92HD71B8_2 HDA_CODEC_CONSTRUCT(IDT, 0x76b1) +#define HDA_CODEC_IDT92HD71B7 HDA_CODEC_CONSTRUCT(IDT, 0x76b2) +#define HDA_CODEC_IDT92HD71B7_2 HDA_CODEC_CONSTRUCT(IDT, 0x76b3) +#define HDA_CODEC_IDT92HD71B6 HDA_CODEC_CONSTRUCT(IDT, 0x76b4) +#define HDA_CODEC_IDT92HD71B6_2 HDA_CODEC_CONSTRUCT(IDT, 0x76b5) +#define HDA_CODEC_IDT92HD71B5 HDA_CODEC_CONSTRUCT(IDT, 0x76b6) +#define HDA_CODEC_IDT92HD71B5_2 HDA_CODEC_CONSTRUCT(IDT, 0x76b7) +#define HDA_CODEC_IDT92HD89C3 HDA_CODEC_CONSTRUCT(IDT, 0x76c0) +#define HDA_CODEC_IDT92HD89C2 HDA_CODEC_CONSTRUCT(IDT, 0x76c1) +#define HDA_CODEC_IDT92HD89C1 HDA_CODEC_CONSTRUCT(IDT, 0x76c2) +#define HDA_CODEC_IDT92HD89B3 HDA_CODEC_CONSTRUCT(IDT, 0x76c3) +#define HDA_CODEC_IDT92HD89B2 HDA_CODEC_CONSTRUCT(IDT, 0x76c4) +#define HDA_CODEC_IDT92HD89B1 HDA_CODEC_CONSTRUCT(IDT, 0x76c5) +#define HDA_CODEC_IDT92HD89E3 HDA_CODEC_CONSTRUCT(IDT, 0x76c6) +#define HDA_CODEC_IDT92HD89E2 HDA_CODEC_CONSTRUCT(IDT, 0x76c7) +#define HDA_CODEC_IDT92HD89E1 HDA_CODEC_CONSTRUCT(IDT, 0x76c8) +#define HDA_CODEC_IDT92HD89D3 HDA_CODEC_CONSTRUCT(IDT, 0x76c9) +#define HDA_CODEC_IDT92HD89D2 HDA_CODEC_CONSTRUCT(IDT, 0x76ca) +#define HDA_CODEC_IDT92HD89D1 HDA_CODEC_CONSTRUCT(IDT, 0x76cb) +#define HDA_CODEC_IDT92HD89F3 HDA_CODEC_CONSTRUCT(IDT, 0x76cc) +#define HDA_CODEC_IDT92HD89F2 HDA_CODEC_CONSTRUCT(IDT, 0x76cd) +#define HDA_CODEC_IDT92HD89F1 HDA_CODEC_CONSTRUCT(IDT, 0x76ce) +#define HDA_CODEC_IDT92HD87B1_3 HDA_CODEC_CONSTRUCT(IDT, 0x76d1) +#define HDA_CODEC_IDT92HD83C1C HDA_CODEC_CONSTRUCT(IDT, 0x76d4) +#define HDA_CODEC_IDT92HD81B1C HDA_CODEC_CONSTRUCT(IDT, 0x76d5) +#define HDA_CODEC_IDT92HD87B2_4 HDA_CODEC_CONSTRUCT(IDT, 0x76d9) +#define HDA_CODEC_IDT92HD93BXX HDA_CODEC_CONSTRUCT(IDT, 0x76df) +#define HDA_CODEC_IDT92HD91BXX HDA_CODEC_CONSTRUCT(IDT, 0x76e0) +#define HDA_CODEC_IDT92HD98BXX HDA_CODEC_CONSTRUCT(IDT, 0x76e3) +#define HDA_CODEC_IDT92HD99BXX HDA_CODEC_CONSTRUCT(IDT, 0x76e5) +#define HDA_CODEC_IDT92HD90BXX HDA_CODEC_CONSTRUCT(IDT, 0x76e7) +#define HDA_CODEC_IDT92HD66B1X5 HDA_CODEC_CONSTRUCT(IDT, 0x76e8) +#define HDA_CODEC_IDT92HD66B2X5 HDA_CODEC_CONSTRUCT(IDT, 0x76e9) +#define HDA_CODEC_IDT92HD66B3X5 HDA_CODEC_CONSTRUCT(IDT, 0x76ea) +#define HDA_CODEC_IDT92HD66C1X5 HDA_CODEC_CONSTRUCT(IDT, 0x76eb) +#define HDA_CODEC_IDT92HD66C2X5 HDA_CODEC_CONSTRUCT(IDT, 0x76ec) +#define HDA_CODEC_IDT92HD66C3X5 HDA_CODEC_CONSTRUCT(IDT, 0x76ed) +#define HDA_CODEC_IDT92HD66B1X3 HDA_CODEC_CONSTRUCT(IDT, 0x76ee) +#define HDA_CODEC_IDT92HD66B2X3 HDA_CODEC_CONSTRUCT(IDT, 0x76ef) +#define HDA_CODEC_IDT92HD66B3X3 HDA_CODEC_CONSTRUCT(IDT, 0x76f0) +#define HDA_CODEC_IDT92HD66C1X3 HDA_CODEC_CONSTRUCT(IDT, 0x76f1) +#define HDA_CODEC_IDT92HD66C2X3 HDA_CODEC_CONSTRUCT(IDT, 0x76f2) +#define HDA_CODEC_IDT92HD66C3_65 HDA_CODEC_CONSTRUCT(IDT, 0x76f3) +#define HDA_CODEC_IDTXXXX HDA_CODEC_CONSTRUCT(IDT, 0xffff) + +/* Silicon Image */ +#define SII_VENDORID 0x1095 +#define HDA_CODEC_SII1390 HDA_CODEC_CONSTRUCT(SII, 0x1390) +#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392) +#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff) + +/* Lucent/Agere */ +#define AGERE_VENDORID 0x11c1 +#define HDA_CODEC_AGEREXXXX HDA_CODEC_CONSTRUCT(AGERE, 0xffff) + +/* Conexant */ +#define CONEXANT_VENDORID 0x14f1 +#define HDA_CODEC_CX20549 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045) +#define HDA_CODEC_CX20551 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047) +#define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) +#define HDA_CODEC_CX20582 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5066) +#define HDA_CODEC_CX20583 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5067) +#define HDA_CODEC_CX20584 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5068) +#define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) +#define HDA_CODEC_CX20588 HDA_CODEC_CONSTRUCT(CONEXANT, 0x506c) +#define HDA_CODEC_CX20590 HDA_CODEC_CONSTRUCT(CONEXANT, 0x506e) +#define HDA_CODEC_CX20631 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5097) +#define HDA_CODEC_CX20632 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5098) +#define HDA_CODEC_CX20641 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a1) +#define HDA_CODEC_CX20642 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a2) +#define HDA_CODEC_CX20651 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ab) +#define HDA_CODEC_CX20652 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ac) +#define HDA_CODEC_CX20664 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b8) +#define HDA_CODEC_CX20665 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b9) +#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) + +/* VIA */ +#define VIA_VENDORID 0x1106 +#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708) +#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709) +#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a) +#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b) +#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710) +#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711) +#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712) +#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713) +#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714) +#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715) +#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716) +#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717) +#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720) +#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721) +#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722) +#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723) +#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724) +#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725) +#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726) +#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727) +#define HDA_CODEC_VT1708S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0397) +#define HDA_CODEC_VT1708S_1 HDA_CODEC_CONSTRUCT(VIA, 0x1397) +#define HDA_CODEC_VT1708S_2 HDA_CODEC_CONSTRUCT(VIA, 0x2397) +#define HDA_CODEC_VT1708S_3 HDA_CODEC_CONSTRUCT(VIA, 0x3397) +#define HDA_CODEC_VT1708S_4 HDA_CODEC_CONSTRUCT(VIA, 0x4397) +#define HDA_CODEC_VT1708S_5 HDA_CODEC_CONSTRUCT(VIA, 0x5397) +#define HDA_CODEC_VT1708S_6 HDA_CODEC_CONSTRUCT(VIA, 0x6397) +#define HDA_CODEC_VT1708S_7 HDA_CODEC_CONSTRUCT(VIA, 0x7397) +#define HDA_CODEC_VT1702_0 HDA_CODEC_CONSTRUCT(VIA, 0x0398) +#define HDA_CODEC_VT1702_1 HDA_CODEC_CONSTRUCT(VIA, 0x1398) +#define HDA_CODEC_VT1702_2 HDA_CODEC_CONSTRUCT(VIA, 0x2398) +#define HDA_CODEC_VT1702_3 HDA_CODEC_CONSTRUCT(VIA, 0x3398) +#define HDA_CODEC_VT1702_4 HDA_CODEC_CONSTRUCT(VIA, 0x4398) +#define HDA_CODEC_VT1702_5 HDA_CODEC_CONSTRUCT(VIA, 0x5398) +#define HDA_CODEC_VT1702_6 HDA_CODEC_CONSTRUCT(VIA, 0x6398) +#define HDA_CODEC_VT1702_7 HDA_CODEC_CONSTRUCT(VIA, 0x7398) +#define HDA_CODEC_VT1716S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0433) +#define HDA_CODEC_VT1716S_1 HDA_CODEC_CONSTRUCT(VIA, 0xa721) +#define HDA_CODEC_VT1718S_0 HDA_CODEC_CONSTRUCT(VIA, 0x0428) +#define HDA_CODEC_VT1718S_1 HDA_CODEC_CONSTRUCT(VIA, 0x4428) +#define HDA_CODEC_VT1802_0 HDA_CODEC_CONSTRUCT(VIA, 0x0446) +#define HDA_CODEC_VT1802_1 HDA_CODEC_CONSTRUCT(VIA, 0x8446) +#define HDA_CODEC_VT1812 HDA_CODEC_CONSTRUCT(VIA, 0x0448) +#define HDA_CODEC_VT1818S HDA_CODEC_CONSTRUCT(VIA, 0x0440) +#define HDA_CODEC_VT1828S HDA_CODEC_CONSTRUCT(VIA, 0x4441) +#define HDA_CODEC_VT2002P_0 HDA_CODEC_CONSTRUCT(VIA, 0x0438) +#define HDA_CODEC_VT2002P_1 HDA_CODEC_CONSTRUCT(VIA, 0x4438) +#define HDA_CODEC_VT2020 HDA_CODEC_CONSTRUCT(VIA, 0x0441) +#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff) + +/* ATI */ +#define ATI_VENDORID 0x1002 +#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c) +#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919) +#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a) +#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01) +#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff) + +/* NVIDIA */ +#define NVIDIA_VENDORID 0x10de +#define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) +#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0003) +#define HDA_CODEC_NVIDIAMCP78_3 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0005) +#define HDA_CODEC_NVIDIAMCP78_4 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) +#define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) +#define HDA_CODEC_NVIDIAGT220 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a) +#define HDA_CODEC_NVIDIAGT21X HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b) +#define HDA_CODEC_NVIDIAMCP89 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000c) +#define HDA_CODEC_NVIDIAGT240 HDA_CODEC_CONSTRUCT(NVIDIA, 0x000d) +#define HDA_CODEC_NVIDIAGTX470 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0010) +#define HDA_CODEC_NVIDIAGTS450 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0011) +#define HDA_CODEC_NVIDIAGT440 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0014) +#define HDA_CODEC_NVIDIAGTX550 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0015) +#define HDA_CODEC_NVIDIAGTX570 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0018) +#define HDA_CODEC_NVIDIAGT610 HDA_CODEC_CONSTRUCT(NVIDIA, 0x001c) // new +#define HDA_CODEC_NVIDIATEGRA30 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0020) // new +#define HDA_CODEC_NVIDIATEGRA114 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0022) // new +#define HDA_CODEC_NVIDIATEGRA124 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0028) // new +#define HDA_CODEC_NVIDIATEGRA210 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0029) // new +#define HDA_CODEC_NVIDIAGTX680 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0040) +#define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) +#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) +#define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) + +/* Chrontel */ +#define CHRONTEL_VENDORID 0x17e8 +#define HDA_CODEC_CHXXXX HDA_CODEC_CONSTRUCT(CHRONTEL, 0xffff) + +/* INTEL */ +#define INTEL_VENDORID 0x8086 +#define HDA_CODEC_INTELIP HDA_CODEC_CONSTRUCT(INTEL, 0x0054) +#define HDA_CODEC_INTELBL HDA_CODEC_CONSTRUCT(INTEL, 0x2801) +#define HDA_CODEC_INTELCA HDA_CODEC_CONSTRUCT(INTEL, 0x2802) +#define HDA_CODEC_INTELEL HDA_CODEC_CONSTRUCT(INTEL, 0x2803) +#define HDA_CODEC_INTELIP2 HDA_CODEC_CONSTRUCT(INTEL, 0x2804) +#define HDA_CODEC_INTELCPT HDA_CODEC_CONSTRUCT(INTEL, 0x2805) +#define HDA_CODEC_INTELPPT HDA_CODEC_CONSTRUCT(INTEL, 0x2806) +#define HDA_CODEC_INTELHSW HDA_CODEC_CONSTRUCT(INTEL, 0x2807) // new +#define HDA_CODEC_INTELBDW HDA_CODEC_CONSTRUCT(INTEL, 0x2808) // new +#define HDA_CODEC_INTELSKLK HDA_CODEC_CONSTRUCT(INTEL, 0x2809) // new +#define HDA_CODEC_INTELKBLK HDA_CODEC_CONSTRUCT(INTEL, 0x280b) // new +#define HDA_CODEC_INTELCL HDA_CODEC_CONSTRUCT(INTEL, 0x29fb) +#define HDA_CODEC_INTELWB HDA_CODEC_CONSTRUCT(INTEL, 0x0a0c) // new +#define HDA_CODEC_INTELXXXX HDA_CODEC_CONSTRUCT(INTEL, 0xffff) + +// +// NOTE: I don't have all the revisions, I included only the ones that I know. +// Codec Name can be different based on revisions, but I have included only +// the codec names that I know. +// +static const struct {UInt32 id; UInt16 rev; char *name;} gCodecList[] = { + // Codec Constant Revision Codec Name + { HDA_CODEC_CS4206, 0x0000, "Cirrus Logic CS4206" }, + { HDA_CODEC_CS4207, 0x0000, "Cirrus Logic CS4207" }, + { HDA_CODEC_CS4210, 0x0000, "Cirrus Logic CS4210" }, + { HDA_CODEC_ALC221, 0x0000, "Realtek ALC221" }, + { HDA_CODEC_ALC260, 0x0000, "Realtek ALC260" }, + { HDA_CODEC_ALC262, 0x0000, "Realtek ALC262" }, + { HDA_CODEC_ALC267, 0x0000, "Realtek ALC267" }, + { HDA_CODEC_ALC268, 0x0000, "Realtek ALC268" }, + { HDA_CODEC_ALC268, 0x0003, "Realtek ALC268" }, + { HDA_CODEC_ALC268, 0x0101, "Realtek ALC268" }, + { HDA_CODEC_ALC269, 0x0000, "Realtek ALC269" }, + { HDA_CODEC_ALC269, 0x0004, "Realtek ALC269" }, + { HDA_CODEC_ALC269, 0x0100, "Realtek ALC269VB" }, + { HDA_CODEC_ALC269, 0x0202, "Realtek ALC269VC" }, + { HDA_CODEC_ALC269, 0x0203, "Realtek ALC269VC" }, + { HDA_CODEC_ALC270, 0x0000, "Realtek ALC270" }, + { HDA_CODEC_ALC270, 0x0100, "Realtek ALC270" }, + { HDA_CODEC_ALC272, 0x0000, "Realtek ALC272" }, + { HDA_CODEC_ALC272, 0x0001, "Realtek ALC272" }, + { HDA_CODEC_ALC273, 0x0000, "Realtek ALC273" }, + { HDA_CODEC_ALC275, 0x0000, "Realtek ALC275" }, + { HDA_CODEC_ALC276, 0x0000, "Realtek ALC276" }, + { HDA_CODEC_ALC660, 0x0000, "Realtek ALC660" }, + { HDA_CODEC_ALC662, 0x0000, "Realtek ALC662" }, + { HDA_CODEC_ALC662, 0x0002, "Realtek ALC662v2" }, + { HDA_CODEC_ALC663, 0x0000, "Realtek ALC663" }, + { HDA_CODEC_ALC665, 0x0000, "Realtek ALC665" }, + { HDA_CODEC_ALC670, 0x0000, "Realtek ALC670" }, + { HDA_CODEC_ALC680, 0x0000, "Realtek ALC680" }, + { HDA_CODEC_ALC861, 0x0000, "Realtek ALC861" }, + { HDA_CODEC_ALC861VD, 0x0000, "Realtek ALC861-VD" }, + { HDA_CODEC_ALC880, 0x0000, "Realtek ALC880" }, + { HDA_CODEC_ALC882, 0x0000, "Realtek ALC882" }, + { HDA_CODEC_ALC883, 0x0000, "Realtek ALC883" }, + { HDA_CODEC_ALC885, 0x0000, "Realtek ALC885" }, + { HDA_CODEC_ALC885, 0x0004, "Realtek ALC889A/ALC885" }, + { HDA_CODEC_ALC885, 0x0103, "Realtek ALC889A" }, + { HDA_CODEC_ALC885, 0x0101, "Realtek ALC889A" }, + { HDA_CODEC_ALC887, 0x0302, "Realtek ALC888B" }, + { HDA_CODEC_ALC887, 0x0002, "Realtek ALC887-VD2" }, + { HDA_CODEC_ALC887, 0x0001, "Realtek ALC887-VD" }, + { HDA_CODEC_ALC887, 0x0000, "Realtek ALC887" }, + { HDA_CODEC_ALC888, 0x0003, "Realtek ALC888S-VD" }, + { HDA_CODEC_ALC888, 0x0002, "Realtek ALC888S-VC" }, + { HDA_CODEC_ALC888, 0x0001, "Realtek ALC888S" }, + { HDA_CODEC_ALC888, 0x0000, "Realtek ALC888" }, + { HDA_CODEC_ALC889, 0x0000, "Realtek ALC889" }, + { HDA_CODEC_ALC892, 0x0000, "Realtek ALC892" }, + { HDA_CODEC_ALC898, 0x0000, "Realtek ALC898" }, + { HDA_CODEC_ALC1150, 0x0000, "Realtek ALC1150" }, + { HDA_CODEC_AD1882, 0x0000, "Analog Devices AD1882" }, + { HDA_CODEC_AD1882A, 0x0000, "Analog Devices AD1882A" }, + { HDA_CODEC_AD1883, 0x0000, "Analog Devices AD1883" }, + { HDA_CODEC_AD1884, 0x0000, "Analog Devices AD1884" }, + { HDA_CODEC_AD1884A, 0x0000, "Analog Devices AD1884A" }, + { HDA_CODEC_AD1981HD, 0x0000, "Analog Devices AD1981HD" }, + { HDA_CODEC_AD1983, 0x0000, "Analog Devices AD1983" }, + { HDA_CODEC_AD1984, 0x0000, "Analog Devices AD1984" }, + { HDA_CODEC_AD1984A, 0x0000, "Analog Devices AD1984A" }, + { HDA_CODEC_AD1984B, 0x0000, "Analog Devices AD1984B" }, + { HDA_CODEC_AD1986A, 0x0000, "Analog Devices AD1986A" }, + { HDA_CODEC_AD1987, 0x0000, "Analog Devices AD1987" }, + { HDA_CODEC_AD1988, 0x0000, "Analog Devices AD1988A" }, + { HDA_CODEC_AD1988B, 0x0000, "Analog Devices AD1988B" }, + { HDA_CODEC_AD1989A, 0x0000, "Analog Devices AD1989A" }, + { HDA_CODEC_AD1989B, 0x0000, "Analog Devices AD2000b" }, + { HDA_CODEC_CA0110, 0x0000, "Creative CA0110-IBG" }, + { HDA_CODEC_CA0110_2, 0x0000, "Creative CA0110-IBG" }, + { HDA_CODEC_CA0132, 0x0000, "Creative CA0132" }, + { HDA_CODEC_SB0880, 0x0000, "Creative SB0880 X-Fi" }, + { HDA_CODEC_CMI9880, 0x0000, "CMedia CMI9880" }, + { HDA_CODEC_CMI98802, 0x0000, "CMedia CMI9880" }, + { HDA_CODEC_CXD9872RDK, 0x0000, "Sigmatel CXD9872RD/K" }, + { HDA_CODEC_CXD9872AKD, 0x0000, "Sigmatel CXD9872AKD" }, + { HDA_CODEC_STAC9200D, 0x0000, "Sigmatel STAC9200D" }, + { HDA_CODEC_STAC9204X, 0x0000, "Sigmatel STAC9204X" }, + { HDA_CODEC_STAC9204D, 0x0000, "Sigmatel STAC9204D" }, + { HDA_CODEC_STAC9205X, 0x0000, "Sigmatel STAC9205X" }, + { HDA_CODEC_STAC9205D, 0x0000, "Sigmatel STAC9205D" }, + { HDA_CODEC_STAC9220, 0x0000, "Sigmatel STAC9220" }, + { HDA_CODEC_STAC9220_A1, 0x0000, "Sigmatel STAC9220_A1" }, + { HDA_CODEC_STAC9220_A2, 0x0000, "Sigmatel STAC9220_A2" }, + { HDA_CODEC_STAC9221, 0x0000, "Sigmatel STAC9221" }, + { HDA_CODEC_STAC9221_A2, 0x0000, "Sigmatel STAC9221_A2" }, + { HDA_CODEC_STAC9221D, 0x0000, "Sigmatel STAC9221D" }, + { HDA_CODEC_STAC922XD, 0x0000, "Sigmatel STAC9220D/9223D" }, + { HDA_CODEC_STAC9227X, 0x0000, "Sigmatel STAC9227X" }, + { HDA_CODEC_STAC9227D, 0x0000, "Sigmatel STAC9227D" }, + { HDA_CODEC_STAC9228X, 0x0000, "Sigmatel STAC9228X" }, + { HDA_CODEC_STAC9228D, 0x0000, "Sigmatel STAC9228D" }, + { HDA_CODEC_STAC9229X, 0x0000, "Sigmatel STAC9229X" }, + { HDA_CODEC_STAC9229D, 0x0000, "Sigmatel STAC9229D" }, + { HDA_CODEC_STAC9230X, 0x0000, "Sigmatel STAC9230X" }, + { HDA_CODEC_STAC9230D, 0x0000, "Sigmatel STAC9230D" }, + { HDA_CODEC_STAC9250, 0x0000, "Sigmatel STAC9250" }, + { HDA_CODEC_STAC9251, 0x0000, "Sigmatel STAC9251" }, + { HDA_CODEC_STAC9255, 0x0000, "Sigmatel STAC9255" }, + { HDA_CODEC_STAC9255D, 0x0000, "Sigmatel STAC9255D" }, + { HDA_CODEC_STAC9254, 0x0000, "Sigmatel STAC9254" }, + { HDA_CODEC_STAC9254D, 0x0000, "Sigmatel STAC9254D" }, + { HDA_CODEC_STAC9271X, 0x0000, "Sigmatel STAC9271X" }, + { HDA_CODEC_STAC9271D, 0x0000, "Sigmatel STAC9271D" }, + { HDA_CODEC_STAC9272X, 0x0000, "Sigmatel STAC9272X" }, + { HDA_CODEC_STAC9272D, 0x0000, "Sigmatel STAC9272D" }, + { HDA_CODEC_STAC9273X, 0x0000, "Sigmatel STAC9273X" }, + { HDA_CODEC_STAC9273D, 0x0000, "Sigmatel STAC9273D" }, + { HDA_CODEC_STAC9274, 0x0000, "Sigmatel STAC9274" }, + { HDA_CODEC_STAC9274D, 0x0000, "Sigmatel STAC9274D" }, + { HDA_CODEC_STAC9274X5NH, 0x0000, "Sigmatel STAC9274X5NH" }, + { HDA_CODEC_STAC9274D5NH, 0x0000, "Sigmatel STAC9274D5NH" }, + { HDA_CODEC_STAC9872AK, 0x0000, "Sigmatel STAC9872AK" }, + { HDA_CODEC_IDT92HD005, 0x0000, "IDT 92HD005" }, + { HDA_CODEC_IDT92HD005D, 0x0000, "IDT 92HD005D" }, + { HDA_CODEC_IDT92HD206X, 0x0000, "IDT 92HD206X" }, + { HDA_CODEC_IDT92HD206D, 0x0000, "IDT 92HD206D" }, + { HDA_CODEC_IDT92HD66B1X5, 0x0000, "IDT 92HD66B1X5" }, + { HDA_CODEC_IDT92HD66B2X5, 0x0000, "IDT 92HD66B2X5" }, + { HDA_CODEC_IDT92HD66B3X5, 0x0000, "IDT 92HD66B3X5" }, + { HDA_CODEC_IDT92HD66C1X5, 0x0000, "IDT 92HD66C1X5" }, + { HDA_CODEC_IDT92HD66C2X5, 0x0000, "IDT 92HD66C2X5" }, + { HDA_CODEC_IDT92HD66C3X5, 0x0000, "IDT 92HD66C3X5" }, + { HDA_CODEC_IDT92HD66B1X3, 0x0000, "IDT 92HD66B1X3" }, + { HDA_CODEC_IDT92HD66B2X3, 0x0000, "IDT 92HD66B2X3" }, + { HDA_CODEC_IDT92HD66B3X3, 0x0000, "IDT 92HD66B3X3" }, + { HDA_CODEC_IDT92HD66C1X3, 0x0000, "IDT 92HD66C1X3" }, + { HDA_CODEC_IDT92HD66C2X3, 0x0000, "IDT 92HD66C2X3" }, + { HDA_CODEC_IDT92HD66C3_65, 0x0000, "IDT 92HD66C3_65" }, + { HDA_CODEC_IDT92HD700X, 0x0000, "IDT 92HD700X" }, + { HDA_CODEC_IDT92HD700D, 0x0000, "IDT 92HD700D" }, + { HDA_CODEC_IDT92HD71B5, 0x0000, "IDT 92HD71B5" }, + { HDA_CODEC_IDT92HD71B5_2, 0x0000, "IDT 92HD71B5" }, + { HDA_CODEC_IDT92HD71B6, 0x0000, "IDT 92HD71B6" }, + { HDA_CODEC_IDT92HD71B6_2, 0x0000, "IDT 92HD71B6" }, + { HDA_CODEC_IDT92HD71B7, 0x0000, "IDT 92HD71B7" }, + { HDA_CODEC_IDT92HD71B7_2, 0x0000, "IDT 92HD71B7" }, + { HDA_CODEC_IDT92HD71B8, 0x0000, "IDT 92HD71B8" }, + { HDA_CODEC_IDT92HD71B8_2, 0x0000, "IDT 92HD71B8" }, + { HDA_CODEC_IDT92HD73C1, 0x0000, "IDT 92HD73C1" }, + { HDA_CODEC_IDT92HD73D1, 0x0000, "IDT 92HD73D1" }, + { HDA_CODEC_IDT92HD73E1, 0x0000, "IDT 92HD73E1" }, + { HDA_CODEC_IDT92HD75B3, 0x0000, "IDT 92HD75B3" }, + { HDA_CODEC_IDT92HD75BX, 0x0000, "IDT 92HD75BX" }, + { HDA_CODEC_IDT92HD81B1C, 0x0000, "IDT 92HD81B1C" }, + { HDA_CODEC_IDT92HD81B1X, 0x0000, "IDT 92HD81B1X" }, + { HDA_CODEC_IDT92HD83C1C, 0x0000, "IDT 92HD83C1C" }, + { HDA_CODEC_IDT92HD83C1X, 0x0000, "IDT 92HD83C1X" }, + { HDA_CODEC_IDT92HD87B1_3, 0x0000, "IDT 92HD87B1/3" }, + { HDA_CODEC_IDT92HD87B2_4, 0x0000, "IDT 92HD87B2/4" }, + { HDA_CODEC_IDT92HD89C3, 0x0000, "IDT 92HD89C3" }, + { HDA_CODEC_IDT92HD89C2, 0x0000, "IDT 92HD89C2" }, + { HDA_CODEC_IDT92HD89C1, 0x0000, "IDT 92HD89C1" }, + { HDA_CODEC_IDT92HD89B3, 0x0000, "IDT 92HD89B3" }, + { HDA_CODEC_IDT92HD89B2, 0x0000, "IDT 92HD89B2" }, + { HDA_CODEC_IDT92HD89B1, 0x0000, "IDT 92HD89B1" }, + { HDA_CODEC_IDT92HD89E3, 0x0000, "IDT 92HD89E3" }, + { HDA_CODEC_IDT92HD89E2, 0x0000, "IDT 92HD89E2" }, + { HDA_CODEC_IDT92HD89E1, 0x0000, "IDT 92HD89E1" }, + { HDA_CODEC_IDT92HD89D3, 0x0000, "IDT 92HD89D3" }, + { HDA_CODEC_IDT92HD89D2, 0x0000, "IDT 92HD89D2" }, + { HDA_CODEC_IDT92HD89D1, 0x0000, "IDT 92HD89D1" }, + { HDA_CODEC_IDT92HD89F3, 0x0000, "IDT 92HD89F3" }, + { HDA_CODEC_IDT92HD89F2, 0x0000, "IDT 92HD89F2" }, + { HDA_CODEC_IDT92HD89F1, 0x0000, "IDT 92HD89F1" }, + { HDA_CODEC_IDT92HD90BXX, 0x0000, "IDT 92HD90BXX" }, + { HDA_CODEC_IDT92HD91BXX, 0x0000, "IDT 92HD91BXX" }, + { HDA_CODEC_IDT92HD93BXX, 0x0000, "IDT 92HD93BXX" }, + { HDA_CODEC_IDT92HD98BXX, 0x0000, "IDT 92HD98BXX" }, + { HDA_CODEC_IDT92HD99BXX, 0x0000, "IDT 92HD99BXX" }, + { HDA_CODEC_CX20549, 0x0000, "Conexant CX20549 (Venice)" }, + { HDA_CODEC_CX20551, 0x0000, "Conexant CX20551 (Waikiki)" }, + { HDA_CODEC_CX20561, 0x0000, "Conexant CX20561 (Hermosa)" }, + { HDA_CODEC_CX20582, 0x0000, "Conexant CX20582 (Pebble)" }, + { HDA_CODEC_CX20583, 0x0000, "Conexant CX20583 (Pebble HSF)" }, + { HDA_CODEC_CX20584, 0x0000, "Conexant CX20584" }, + { HDA_CODEC_CX20585, 0x0000, "Conexant CX20585" }, + { HDA_CODEC_CX20588, 0x0000, "Conexant CX20588" }, + { HDA_CODEC_CX20590, 0x0000, "Conexant CX20590" }, + { HDA_CODEC_CX20631, 0x0000, "Conexant CX20631" }, + { HDA_CODEC_CX20632, 0x0000, "Conexant CX20632" }, + { HDA_CODEC_CX20641, 0x0000, "Conexant CX20641" }, + { HDA_CODEC_CX20642, 0x0000, "Conexant CX20642" }, + { HDA_CODEC_CX20651, 0x0000, "Conexant CX20651" }, + { HDA_CODEC_CX20652, 0x0000, "Conexant CX20652" }, + { HDA_CODEC_CX20664, 0x0000, "Conexant CX20664" }, + { HDA_CODEC_CX20665, 0x0000, "Conexant CX20665" }, + { HDA_CODEC_VT1708_8, 0x0000, "VIA VT1708_8" }, + { HDA_CODEC_VT1708_9, 0x0000, "VIA VT1708_9" }, + { HDA_CODEC_VT1708_A, 0x0000, "VIA VT1708_A" }, + { HDA_CODEC_VT1708_B, 0x0000, "VIA VT1708_B" }, + { HDA_CODEC_VT1709_0, 0x0000, "VIA VT1709_0" }, + { HDA_CODEC_VT1709_1, 0x0000, "VIA VT1709_1" }, + { HDA_CODEC_VT1709_2, 0x0000, "VIA VT1709_2" }, + { HDA_CODEC_VT1709_3, 0x0000, "VIA VT1709_3" }, + { HDA_CODEC_VT1709_4, 0x0000, "VIA VT1709_4" }, + { HDA_CODEC_VT1709_5, 0x0000, "VIA VT1709_5" }, + { HDA_CODEC_VT1709_6, 0x0000, "VIA VT1709_6" }, + { HDA_CODEC_VT1709_7, 0x0000, "VIA VT1709_7" }, + { HDA_CODEC_VT1708B_0, 0x0000, "VIA VT1708B_0" }, + { HDA_CODEC_VT1708B_1, 0x0000, "VIA VT1708B_1" }, + { HDA_CODEC_VT1708B_2, 0x0000, "VIA VT1708B_2" }, + { HDA_CODEC_VT1708B_3, 0x0000, "VIA VT1708B_3" }, + { HDA_CODEC_VT1708B_4, 0x0000, "VIA VT1708B_4" }, + { HDA_CODEC_VT1708B_5, 0x0000, "VIA VT1708B_5" }, + { HDA_CODEC_VT1708B_6, 0x0000, "VIA VT1708B_6" }, + { HDA_CODEC_VT1708B_7, 0x0000, "VIA VT1708B_7" }, + { HDA_CODEC_VT1708S_0, 0x0000, "VIA VT1708S_0" }, + { HDA_CODEC_VT1708S_1, 0x0000, "VIA VT1708S_1" }, + { HDA_CODEC_VT1708S_2, 0x0000, "VIA VT1708S_2" }, + { HDA_CODEC_VT1708S_3, 0x0000, "VIA VT1708S_3" }, + { HDA_CODEC_VT1708S_4, 0x0000, "VIA VT1708S_4" }, + { HDA_CODEC_VT1708S_5, 0x0000, "VIA VT1708S_5" }, + { HDA_CODEC_VT1708S_6, 0x0000, "VIA VT1708S_6" }, + { HDA_CODEC_VT1708S_7, 0x0000, "VIA VT1708S_7" }, + { HDA_CODEC_VT1702_0, 0x0000, "VIA VT1702_0" }, + { HDA_CODEC_VT1702_1, 0x0000, "VIA VT1702_1" }, + { HDA_CODEC_VT1702_2, 0x0000, "VIA VT1702_2" }, + { HDA_CODEC_VT1702_3, 0x0000, "VIA VT1702_3" }, + { HDA_CODEC_VT1702_4, 0x0000, "VIA VT1702_4" }, + { HDA_CODEC_VT1702_5, 0x0000, "VIA VT1702_5" }, + { HDA_CODEC_VT1702_6, 0x0000, "VIA VT1702_6" }, + { HDA_CODEC_VT1702_7, 0x0000, "VIA VT1702_7" }, + { HDA_CODEC_VT1716S_0, 0x0000, "VIA VT1716S_0" }, + { HDA_CODEC_VT1716S_1, 0x0000, "VIA VT1716S_1" }, + { HDA_CODEC_VT1718S_0, 0x0000, "VIA VT1718S_0" }, + { HDA_CODEC_VT1718S_1, 0x0000, "VIA VT1718S_1" }, + { HDA_CODEC_VT1802_0, 0x0000, "VIA VT1802_0" }, + { HDA_CODEC_VT1802_1, 0x0000, "VIA VT1802_1" }, + { HDA_CODEC_VT1812, 0x0000, "VIA VT1812" }, + { HDA_CODEC_VT1818S, 0x0000, "VIA VT1818S" }, + { HDA_CODEC_VT1828S, 0x0000, "VIA VT1828S" }, + { HDA_CODEC_VT2002P_0, 0x0000, "VIA VT2002P_0" }, + { HDA_CODEC_VT2002P_1, 0x0000, "VIA VT2002P_1" }, + { HDA_CODEC_VT2020, 0x0100, "VIA VT2020" }, + { HDA_CODEC_ATIRS600_1, 0x0000, "ATI RS600 HDMI" }, + { HDA_CODEC_ATIRS600_2, 0x0000, "ATI RS600 HDMI" }, + { HDA_CODEC_ATIRS690, 0x0000, "ATI RS690/780 HDMI" }, + { HDA_CODEC_ATIR6XX, 0x0000, "ATI R6xx HDMI" }, + { HDA_CODEC_NVIDIAMCP67, 0x0000, "NVidia MCP67 HDMI" }, + { HDA_CODEC_NVIDIAMCP73, 0x0000, "NVidia MCP73 HDMI" }, + { HDA_CODEC_NVIDIAMCP78, 0x0000, "NVidia MCP78 HDMI" }, + { HDA_CODEC_NVIDIAMCP78_2, 0x0000, "NVidia MCP78 HDMI" }, + { HDA_CODEC_NVIDIAMCP78_3, 0x0000, "NVidia MCP78 HDMI" }, + { HDA_CODEC_NVIDIAMCP78_4, 0x0000, "NVidia MCP78 HDMI" }, + { HDA_CODEC_NVIDIAMCP7A, 0x0000, "NVidia MCP7A HDMI" }, + { HDA_CODEC_NVIDIAGT220, 0x0000, "NVidia GT220 HDMI" }, + { HDA_CODEC_NVIDIAGT21X, 0x0000, "NVidia GT21x HDMI" }, + { HDA_CODEC_NVIDIAMCP89, 0x0000, "NVidia MCP89 HDMI" }, + { HDA_CODEC_NVIDIAGT240, 0x0000, "NVidia GT240 HDMI" }, + { HDA_CODEC_NVIDIAGTX470, 0x0000, "NVidia GTX470 HDMI" }, + { HDA_CODEC_NVIDIAGTS450, 0x0000, "NVidia GTS450 HDMI" }, + { HDA_CODEC_NVIDIAGT440, 0x0000, "NVidia GT440 HDMI" }, + { HDA_CODEC_NVIDIAGTX550, 0x0000, "NVidia GTX550 HDMI" }, + { HDA_CODEC_NVIDIAGTX570, 0x0000, "NVidia GTX570 HDMI" }, + { HDA_CODEC_NVIDIAGTX680, 0x0000, "NVidia GTX680 HDMI" }, + { HDA_CODEC_INTELIP, 0x0000, "Intel HD (Ironlake) HDMI" }, + { HDA_CODEC_INTELBL, 0x0000, "Intel 3100/X3500 (Bearlake) HDMI" }, + { HDA_CODEC_INTELCA, 0x0000, "Intel 4500MHD (Cantiga) HDMI" }, + { HDA_CODEC_INTELEL, 0x0000, "Intel (X)4500(HD) (Eaglelake) HDMI" }, + { HDA_CODEC_INTELIP2, 0x0000, "Intel HD (Ironlake) HDMI" }, + { HDA_CODEC_INTELCPT, 0x0000, "Intel HD 3000 (Sandy Bridge) HDMI" }, + { HDA_CODEC_INTELPPT, 0x0000, "Intel HD 4000 (Ivy Bridge) HDMI" }, + { HDA_CODEC_INTELCL, 0x0000, "Intel X3100 (Crestline) HDMI" }, + { HDA_CODEC_SII1390, 0x0000, "Silicon Image SiI1390 HDMI" }, + { HDA_CODEC_SII1392, 0x0000, "Silicon Image SiI1392 HDMI" }, + /* Unknown codec */ + { HDA_CODEC_ADXXXX, 0x0000, "Analog Devices (Unknown)" }, + { HDA_CODEC_AGEREXXXX, 0x0000, "Lucent/Agere Systems (Unknown)" }, + { HDA_CODEC_ALCXXXX, 0x0000, "Realtek (Unknown)" }, + { HDA_CODEC_ATIXXXX, 0x0000, "ATI (Unknown)" }, + { HDA_CODEC_CAXXXX, 0x0000, "Creative (Unknown)" }, + { HDA_CODEC_CMIXXXX, 0x0000, "CMedia (Unknown)" }, + { HDA_CODEC_CMIXXXX2, 0x0000, "CMedia (Unknown)" }, + { HDA_CODEC_CSXXXX, 0x0000, "Cirrus Logic (Unknown)" }, + { HDA_CODEC_CXXXXX, 0x0000, "Conexant (Unknown)" }, + { HDA_CODEC_CHXXXX, 0x0000, "Chrontel (Unknown)" }, + { HDA_CODEC_IDTXXXX, 0x0000, "IDT (Unknown)" }, + { HDA_CODEC_INTELXXXX, 0x0000, "Intel (Unknown)" }, + { HDA_CODEC_MOTOXXXX, 0x0000, "Motorola (Unknown)" }, + { HDA_CODEC_NVIDIAXXXX, 0x0000, "NVidia (Unknown)" }, + { HDA_CODEC_SIIXXXX, 0x0000, "Silicon Image (Unknown)" }, + { HDA_CODEC_STACXXXX, 0x0000, "Sigmatel (Unknown)" }, + { HDA_CODEC_VTXXXX, 0x0000, "VIA (Unknown)" }, + { 0, 0x0000, NULL } +}; + +#endif diff --git a/ComboJack_Source/Combo Jack/hda-verb.m b/ComboJack_Source/Combo Jack/hda-verb.m new file mode 100644 index 0000000..c3cfe58 --- /dev/null +++ b/ComboJack_Source/Combo Jack/hda-verb.m @@ -0,0 +1,1047 @@ +/* + * Accessing HD-audio verbs via hwdep interface + * Version 0.3 + * + * Copyright (c) 2008 Takashi Iwai + * + * Licensed under GPL v2 or later. + */ + +// +// Based on hda-verb from alsa-tools: +// https://www.alsa-project.org/main/index.php/Main_Page +// +// Conceptually derived from ALCPlugFix: +// https://github.com/goodwin/ALCPlugFix +// +// values come from https://github.com/torvalds/linux/blob/master/sound/pci/hda/patch_realtek.c + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PCI.h" +//#include "Tables.h" + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +// For driver +#include "hda_hwdep.h" +//#include "rt298.h" // From Linux +#define REALTEK_VENDOR_REGISTERS 0x20 +#define REALTEK_HP_OUT 0x21 + +#define AC_VERB_GET_STREAM_FORMAT 0x0a00 +#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00 +#define AC_VERB_GET_PROC_COEF 0x0c00 +#define AC_VERB_GET_COEF_INDEX 0x0d00 +#define AC_VERB_PARAMETERS 0x0f00 +#define AC_VERB_GET_CONNECT_SEL 0x0f01 +#define AC_VERB_GET_CONNECT_LIST 0x0f02 +#define AC_VERB_GET_PROC_STATE 0x0f03 +#define AC_VERB_GET_SDI_SELECT 0x0f04 +#define AC_VERB_GET_POWER_STATE 0x0f05 +#define AC_VERB_GET_CONV 0x0f06 +#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07 +#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08 +#define AC_VERB_GET_PIN_SENSE 0x0f09 +#define AC_VERB_GET_BEEP_CONTROL 0x0f0a +#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c +#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d +#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e +#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f +#define AC_VERB_GET_GPIO_DATA 0x0f15 +#define AC_VERB_GET_GPIO_MASK 0x0f16 +#define AC_VERB_GET_GPIO_DIRECTION 0x0f17 +#define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18 +#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 +#define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a +#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c +#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 + +#define AC_VERB_SET_STREAM_FORMAT 0x200 +#define AC_VERB_SET_AMP_GAIN_MUTE 0x300 +#define AC_VERB_SET_PROC_COEF 0x400 +#define AC_VERB_SET_COEF_INDEX 0x500 +#define AC_VERB_SET_CONNECT_SEL 0x701 +#define AC_VERB_SET_PROC_STATE 0x703 +#define AC_VERB_SET_SDI_SELECT 0x704 +#define AC_VERB_SET_POWER_STATE 0x705 +#define AC_VERB_SET_CHANNEL_STREAMID 0x706 +#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707 +#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708 +#define AC_VERB_SET_PIN_SENSE 0x709 +#define AC_VERB_SET_BEEP_CONTROL 0x70a +#define AC_VERB_SET_EAPD_BTLENABLE 0x70c +#define AC_VERB_SET_DIGI_CONVERT_1 0x70d +#define AC_VERB_SET_DIGI_CONVERT_2 0x70e +#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f +#define AC_VERB_SET_GPIO_DATA 0x715 +#define AC_VERB_SET_GPIO_MASK 0x716 +#define AC_VERB_SET_GPIO_DIRECTION 0x717 +#define AC_VERB_SET_GPIO_WAKE_MASK 0x718 +#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 +#define AC_VERB_SET_GPIO_STICKY_MASK 0x71a +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f +#define AC_VERB_SET_CODEC_RESET 0x7ff + +#define AC_PAR_VENDOR_ID 0x00 +#define AC_PAR_SUBSYSTEM_ID 0x01 +#define AC_PAR_REV_ID 0x02 +#define AC_PAR_NODE_COUNT 0x04 +#define AC_PAR_FUNCTION_TYPE 0x05 +#define AC_PAR_AUDIO_FG_CAP 0x08 +#define AC_PAR_AUDIO_WIDGET_CAP 0x09 +#define AC_PAR_PCM 0x0a +#define AC_PAR_STREAM 0x0b +#define AC_PAR_PIN_CAP 0x0c +#define AC_PAR_AMP_IN_CAP 0x0d +#define AC_PAR_CONNLIST_LEN 0x0e +#define AC_PAR_POWER_STATE 0x0f +#define AC_PAR_PROC_CAP 0x10 +#define AC_PAR_GPIO_CAP 0x11 +#define AC_PAR_AMP_OUT_CAP 0x12 +#define AC_PAR_VOL_KNB_CAP 0x13 + +#define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val) +#define WRITE_COEF(_idx, _val) WRITE_COEFEX(REALTEK_VENDOR_REGISTERS, _idx, _val) +#define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(REALTEK_VENDOR_REGISTERS, _idx, _mask, _val) + +#define GETJACKSTATUS() VerbCommand(HDA_VERB(REALTEK_HP_OUT, AC_VERB_GET_PIN_SENSE, 0x00)) +#define VERBSTUB_SERVICE "com_XPS_VerbStub" +#define CODECCOMMANDER_SERVICE "CodecCommander" +#define GET_CFSTR_FROM_DICT(_dict, _key) (__bridge CFStringRef)[_dict objectForKey:_key] + +// +// Global Variables +// +CFURLRef iconUrl = NULL; +io_service_t VerbIOService; +io_connect_t DataConnection; +uint32_t connectiontype = 0; +bool run = true; +bool awake = false; +io_connect_t root_port; +io_object_t notifierObject; +struct stat consoleinfo; + +//get device id +//uint32_t vendor = 0; +//uint32_t device = 0; +long codecID = 0; +uint32_t subVendor = 0; +uint32_t subDevice = 0; +long codecIDArr[4] = {0x10ec0256, 0x10ec0255, 0x10ec0298, 0x10ec0295}; +int xps13SubDev[4] = {0x0704, 0x075b, 0x082a, 0x0923}; + +//dialog text +NSDictionary *l10nDict = nil; +NSDictionary *dlgText; + +// +// Open connection to IOService +// + +uint32_t OpenServiceConnection() +{ + // + // Having a kernel-side server (VerbStub) and a user-side client (hda-verb) is really the only way to ensure that hda- + // verb won't break when IOAudioFamily changes. This 2-component solution is necessary because we can't compile kernel + // libraries into user-space programs on macOS and expect them to work generically. + // + // Additionally, if this program were made as a single executable that accessed device memory regions directly, it would + // only be guaranteed to work for one machine on one BIOS version since memory regions change depending on hardware + // configurations. This is why Raspberry Pis, STM32s, and other embedded platforms are nice to program on: They don't + // change much between versions so programs can be made extremely lightweight. Linux also does a pretty good job + // achieving a similar situation, since everything (devices, buses, etc.) on Linux is represented by an easily + // accessible file (just look at how simple the hda-verb program in alsa-tools is! All it uses is ioctl). + // + + CFMutableDictionaryRef verbDict = IOServiceMatching(VERBSTUB_SERVICE); + CFMutableDictionaryRef codecCommanderDict = IOServiceMatching(CODECCOMMANDER_SERVICE); + + // Use IOServiceGetMatchingService since we can reasonably expect "VerbStub" is the only IORegistryEntry of its kind. + // Otherwise IOServiceGetMatchingServices with an iterating algorithm must be used to find the kernel extension. + + VerbIOService = IOServiceGetMatchingService(kIOMasterPortDefault, verbDict); + + // If VerbStub is not available, try CodecCommander + if (!VerbIOService) { + VerbIOService = IOServiceGetMatchingService(kIOMasterPortDefault, codecCommanderDict); + } + + // Hopefully the kernel extension loaded properly so it can be found. + if (!VerbIOService) + { + fprintf(stderr, "Could not locate VerbStub or CodecCommander kext. Ensure it is loaded; verbs cannot be sent otherwise.\n"); + return -1; + } + + // Connect to the IOService object + // Note: kern_return_t is just an int + kern_return_t kernel_return_status = IOServiceOpen(VerbIOService, mach_task_self(), connectiontype, &DataConnection); + + if (kernel_return_status != kIOReturnSuccess) + { + fprintf(stderr, "Failed to open VerbStub IOService: %08x.\n", kernel_return_status); + return -1; + } + + return kernel_return_status; // 0 if successful +} + +int indexOf(int *array, int array_size, int number) { + for (int i = 0; i < array_size; ++i) { + if (array[i] == number) { + return i; + } + } + return -1; +} + +int indexOf_L(long *array, int array_size, long number) { + for (int i = 0; i < array_size; ++i) { + if (array[i] == number) { + return i; + } + } + return -1; +} + +// +// Send verb command +// + +static uint32_t VerbCommand(uint32_t command) +{ + // + // Call the function ultimately responsible for sending commands in the kernel extension. That function will return the + // response we also want. + // https://lists.apple.com/archives/darwin-drivers/2008/Mar/msg00007.html + // + + uint32_t inputCount = 1; // Number of input arguments + uint32_t outputCount = 1; // Number of elements in output + uint64_t input = command; // Array of input scalars + uint64_t output; // Array of output scalars + + // IOConnectCallScalarMethod was introduced in Mac OS X 10.5 + + kern_return_t kernel_return_status = IOConnectCallScalarMethod(DataConnection, connectiontype, &input, inputCount, &output, &outputCount); + + if (kernel_return_status != kIOReturnSuccess) + { + fprintf(stderr, "Error sending command.\n"); + return -1; + } + + // Return command response + return (uint32_t)output; +} + +// +// Close connection to IOService +// + +void CloseServiceConnection() +{ + // Done with the VerbStub IOService object, so we don't need to hold on to it anymore + IOObjectRelease(VerbIOService); + IODeregisterForSystemPower(¬ifierObject); +} + +// +// UPDATE COEFFICIENTS +// + +static uint32_t UPDATE_COEFEX(uint32_t nid, uint32_t index, uint32_t mask, uint32_t value) +{ + struct hda_verb_ioctl SetCoefIndex; + struct hda_verb_ioctl GetProcCoef; + struct hda_verb_ioctl SetProcCoef; + + //int nid = REALTEK_VENDOR_REGISTERS; // Vendor Register 0x20 in rt298.h + uint32_t tmp; + + SetCoefIndex.verb = HDA_VERB(nid, AC_VERB_SET_COEF_INDEX, index); // Verb to set the coefficient index desired + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); // Go to index desired + if(SetCoefIndex.res != 0) // If uninitialized expect response of -1 (0xFFFFFFFF for uint32_t) + { + fprintf(stderr, "Received weird response 0x%x for command 0x%x\n", SetCoefIndex.res, SetCoefIndex.verb); + return -1; // Fail + } + + GetProcCoef.verb = HDA_VERB(nid, AC_VERB_GET_PROC_COEF, 0x00); // Get Processing Coefficient payload is always 0 + GetProcCoef.res = VerbCommand(GetProcCoef.verb); // Get original data + + tmp = GetProcCoef.res & ~mask; + tmp |= value & mask; + + if (tmp != GetProcCoef.res) + { + // New data to write! + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); // Reset back to the index desired (indices automatically iterate after a read) + + SetProcCoef.verb = HDA_VERB(nid, AC_VERB_SET_PROC_COEF, tmp); + SetProcCoef.res = VerbCommand(SetProcCoef.verb); // Send new processing coefficient + if (SetProcCoef.res != 0) + { + fprintf(stderr, "Received strange response 0x%x for command 0x%x\n", SetCoefIndex.res, SetCoefIndex.verb); + return -1; // Fail + } + } + // Return value just written (or not) as reported by register + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); // Go back to register + GetProcCoef.res = VerbCommand(GetProcCoef.verb); // Get register data + + // Return processing coefficient + return GetProcCoef.res; +} + +static uint32_t alc225_pre_hsmode(){ + UPDATE_COEF(0x4a, 1<<8, 0); + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0); + UPDATE_COEF(0x63, 3<<14, 3<<14); + UPDATE_COEF(0x4a, 3<<4, 2<<4); + UPDATE_COEF(0x4a, 3<<10, 3<<10); + UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10); + UPDATE_COEF(0x4a, 3<<10, 0); + return 0; +} + +// +// Unplugged Settings +// + +static uint32_t unplugged() +{ + fprintf(stderr, "Jack Status: unplugged.\n"); + + switch (codecID) + { + case 0x10ec0255: + WRITE_COEF(0x1b, 0x0c0b); // LDO and MISC control + goto ALC255_256; + case 0x10ec0256: + WRITE_COEF(0x1b, 0x0c4b); // LDO and MISC control + ALC255_256: //common commands for alc255/256 + WRITE_COEF(0x45, 0xd089); /* UAJ function set to menual mode */ + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0); /* Direct Drive HP Amp control(Set to verb control)*/ + WRITE_COEF(0x06, 0x6104); /* Set MIC2 Vref gate with HP */ + WRITE_COEFEX(0x57, 0x03, 0x8aa6); /* Direct Drive HP Amp control */ + //WRITE_COEF(0x46, 0xd089); + break; + case 0x10ec0295: + alc225_pre_hsmode(); + UPDATE_COEF(0x63, 3<<14, 0); + break; + case 0x10ec0298: + UPDATE_COEF(0x4f, 0xfcc0, 0xc400); + UPDATE_COEF(0x50, 0x2000, 0x2000); + UPDATE_COEF(0x56, 0x0006, 0x0006); + UPDATE_COEF(0x66, 0x0008, 0); + UPDATE_COEF(0x67, 0x2000, 0); + // Mac: Need to manually switch the selector back to internal microphone + VerbCommand(HDA_VERB(0x22, AC_VERB_SET_CONNECT_SEL, 0x05)); + break; + default: + break; + } + return 0; // Success +} + +// +// Headphones Settings +// + +static uint32_t headphones() +{ + fprintf(stderr, "Jack Status: headphones plugged in.\n"); + switch (codecID) + { + case 0x10ec0255: + case 0x10ec0256: + //VerbCommand(HDA_VERB(0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20)); + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20)); + WRITE_COEF(0x45, 0xc089); + WRITE_COEF(0x45, 0xc489); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + WRITE_COEF(0x49, 0x0049); + break; + case 0x10ec0295: + alc225_pre_hsmode(); + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20)); + UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10); + UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10); + UPDATE_COEF(0x49, 3<<8, 0<<8); + UPDATE_COEF(0x4a, 3<<4, 3<<4); + UPDATE_COEF(0x63, 3<<14, 0); + UPDATE_COEF(0x67, 0xf000, 0x3000); + break; + case 0x10ec0298: + UPDATE_COEF(0x4f, 0xfcc0, 0xc400); // Set to TRS type + VerbCommand(HDA_VERB(0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20)); // 0x20 corresponds to IN (0x20) + HiZ (0x00) -- Note: HiZ means "High Impedance" + UPDATE_COEF(0x50, 0x2000, 0x2000); + UPDATE_COEF(0x56, 0x0006, 0x0006); + UPDATE_COEF(0x66, 0x0008, 0); + UPDATE_COEF(0x67, 0x2000, 0); + break; + default: + break; + } + return 0; // Success +} + +// +// Line-In Settings +// + +static uint32_t linein() +{ + fprintf(stderr, "Jack Status: line-in device plugged in.\n"); + + //alc_headset_mode_mic_in + switch (codecID) + { + case 0x10ec0255: + case 0x10ec0256: + return headphones(); //line-in does not work + //VerbCommand(HDA_VERB(0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0)); // Disable headphone output + //WRITE_COEFEX(0x57, 0x03, 0x8aa6); + //WRITE_COEF(0x06, 0x6100); + break; + case 0x10ec0295: + alc225_pre_hsmode(); + UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10); + VerbCommand(HDA_VERB(0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0)); + WRITE_COEFEX(0x57, 0x03, 0x8aa6); + WRITE_COEF(0x06, 0x6100); /* Set MIC2 Vref gate to normal */ + break; + case 0x10ec0298: + UPDATE_COEF(0x4f, 0x000c, 0x0); + //set 0x21 pin_w 0 here + VerbCommand(HDA_VERB(0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0)); // Disable headphone output + UPDATE_COEF(0x50, 0x2000, 0); + UPDATE_COEF(0x56, 0x0006, 0); + UPDATE_COEF(0x4f, 0xfcc0, 0xc400); //Set to TRS type + UPDATE_COEF(0x66, 0x0008, 0x0008); + UPDATE_COEF(0x67, 0x2000, 0x2000); + break; + default: + break; + } + + //set 0x1a pin_w 0x21 here + // 0x21 corresponds to IN (0x20) + VREF 50 (0x01) + VerbCommand(HDA_VERB(0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x21)); + // Mac: Check power state of node 0x1a since it's frequently in D3 + if (VerbCommand(HDA_VERB(0x1a, AC_VERB_GET_POWER_STATE, 0x00)) != 0) + { + // Mac: Power on node 0x1a if in D3 + VerbCommand(HDA_VERB(0x1a, AC_VERB_SET_POWER_STATE, 0x00)); + } + // Mac: Need to manually switch the selector to line-in node + VerbCommand(HDA_VERB(0x22, AC_VERB_SET_CONNECT_SEL, 0x02)); + + return 0; // Success +} + + +// +// Headset: CTIA (iPhone-style plug) +// + +static uint32_t headsetCTIA() +{ + fprintf(stderr, "Jack Status: headset (CTIA/iPhone) plugged in.\n"); + + //alc_headset_mode_ctia + switch (codecID) + { + case 0x10ec0255: + WRITE_COEF(0x45, 0xd489); //Set to CTIA type + WRITE_COEF(0x1b, 0x0c2b); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + break; + case 0x10ec0256: + WRITE_COEF(0x45, 0xd489); //Set to CTIA type + WRITE_COEF(0x1b, 0x0c6b); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + break; + case 0x10ec0295: + UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10); + UPDATE_COEF(0x63, 3<<14, 1<<14); + break; + case 0x10ec0298: + UPDATE_COEF(0x8e, 0x0070, 0x0020); // Headset output enable + UPDATE_COEF(0x4f, 0xfcc0, 0xd400); + usleep(300000); + UPDATE_COEF(0x50, 0x2000, 0x2000); + UPDATE_COEF(0x56, 0x0006, 0x0006); + UPDATE_COEF(0x66, 0x0008, 0); + UPDATE_COEF(0x67, 0x2000, 0); + // Mac: Need to manually switch the selector to headset node + VerbCommand(HDA_VERB(0x22, AC_VERB_SET_CONNECT_SEL, 0x00)); + break; + default: + break; + } + + return 0; // Success +} + +// +// Headset: OMTP (Nokia-style plug) +// + +static uint32_t headsetOMTP() +{ + fprintf(stderr, "Jack Status: headset (OMTP/Nokia) plugged in.\n"); + /* + //alc288 + UPDATE_COEF(0x4f, 0xfcc0, 0xe400); + usleep(300000); + UPDATE_COEF(0x50, 0x2000, 0x2000); + UPDATE_COEF(0x56, 0x0006, 0x0006); + UPDATE_COEF(0x66, 0x0008, 0); + UPDATE_COEF(0x67, 0x2000, 0); + */ + //alc256 + switch (codecID) + { + case 0x10ec0255: + WRITE_COEF(0x45, 0xe489); + WRITE_COEF(0x1b, 0x0c2b); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + break; + case 0x10ec0256: + WRITE_COEF(0x45, 0xe489); + WRITE_COEF(0x1b, 0x0c6b); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + break; + case 0x10ec0295: + WRITE_COEF(0x45, 0xe489); /* Set to OMTP Type */ + WRITE_COEF(0x1b, 0x0c2b); + WRITE_COEFEX(0x57, 0x03, 0x8ea6); + break; + case 0x10ec0298: + UPDATE_COEF(0x4f, 0xfcc0, 0xe400); + usleep(300000); + UPDATE_COEF(0x50, 0x2000, 0x2000); + UPDATE_COEF(0x56, 0x0006, 0x0006); + UPDATE_COEF(0x66, 0x0008, 0); + UPDATE_COEF(0x67, 0x2000, 0); + // Mac: Need to manually switch the selector to headset node + VerbCommand(HDA_VERB(0x22, AC_VERB_SET_CONNECT_SEL, 0x00)); + break; + default: + break; + } + + return 0; // Success +} + +// +// Headset Auto-Detection (CTIA/OMTP) +// + +static uint32_t headsetcheck() +{ + struct hda_verb_ioctl SetCoefIndex; + struct hda_verb_ioctl GetProcCoef; + uint32_t retval; + + int nid = REALTEK_VENDOR_REGISTERS; +// bool is_ctia; + + fprintf(stderr, "Jack Status: headset plugged in. Checking type...\n"); + + switch (codecID) + { + case 0x10ec0255: + case 0x10ec0256: + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24)); // 0x24 corresponds to IN (0x20) + VREF 80 (0x04) + WRITE_COEF(0x45, 0xd089); + WRITE_COEF(0x49, 0x0149); + usleep(350000); + // Read register 0x46 + SetCoefIndex.verb = HDA_VERB(nid, AC_VERB_SET_COEF_INDEX, 0x46); + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); + GetProcCoef.verb = HDA_VERB(nid, AC_VERB_GET_PROC_COEF, 0x46); + GetProcCoef.res = VerbCommand(GetProcCoef.verb); + break; + case 0x10ec0295: + alc225_pre_hsmode(); + UPDATE_COEF(0x67, 0xf000, 0x1000); //Headset output enable + UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10); //Headset output enable + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24)); // 0x24 corresponds to IN (0x20) + VREF 80 (0x04) + UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10); //Check Type + UPDATE_COEF(0x49, 3<<8, 2<<8); //Check Type + usleep(350000); + // Read register 0x50 + SetCoefIndex.verb = HDA_VERB(nid, AC_VERB_SET_COEF_INDEX, 0x46); // Verb to set the coefficient index desired + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); // Go to index desired + GetProcCoef.verb = HDA_VERB(nid, AC_VERB_GET_PROC_COEF, 0x00); // Get Processing Coefficient payload is always 0 + GetProcCoef.res = VerbCommand(GetProcCoef.verb); // Get data + break; + case 0x10ec0298: + UPDATE_COEF(0x8e, 0x0070, 0x0020); //Headset output enable + VerbCommand(HDA_VERB(0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24)); // 0x24 corresponds to IN (0x20) + VREF 80 (0x04) + UPDATE_COEF(0x4f, 0xfcc0, 0xd400); //Check Type + usleep(350000); + // Read register 0x50 + SetCoefIndex.verb = HDA_VERB(nid, AC_VERB_SET_COEF_INDEX, 0x50); // Verb to set the coefficient index desired + SetCoefIndex.res = VerbCommand(SetCoefIndex.verb); // Go to index desired + GetProcCoef.verb = HDA_VERB(nid, AC_VERB_GET_PROC_COEF, 0x00); // Get Processing Coefficient payload is always 0 + GetProcCoef.res = VerbCommand(GetProcCoef.verb); // Get data + break; + default: + break; + } + + // Check if register 0x50 reports a CTIA- or OMTP-style headset + fprintf(stderr, "Headset check: 0x%x, 0x%x\n", GetProcCoef.res, GetProcCoef.res & 0x0070); + if ((GetProcCoef.res & 0x0070) == 0x0070) + { + retval = headsetCTIA(); + } + else + { + retval = headsetOMTP(); + } + + WRITE_COEF(0x06, 0x6104); +// is_ctia = (GetProcCoef.res & 0x0070) == 0x0070; <-- Wow. + + return retval; // Success +} + +// +// Jack unplug monitor +// + +void JackBehavior() +{ + int counter = 4; + + while (run) // Poll headphone jack state + { + usleep(250*1000); // Polling frequency (seconds): use usleep for microseconds if finer-grained control is needed + if (awake) + { + awake = false; + break; + } + + if ((GETJACKSTATUS() & 0x80000000) != 0x80000000) + { + if (--counter < 0) + break; + } + else + counter = 4; + } + if (run) // If process is killed, maintain current state + { + fprintf(stderr, "Unplugged.\n"); + unplugged(); // Clean up, jack's been unplugged or process was killed + } +} + +// +// Pop-up menu +// + +uint32_t CFPopUpMenu() +{ + CFOptionFlags responsecode = kCFUserNotificationOtherResponse; + +// while (true) +// { +// //wait until user logged in +// stat("/dev/console", &consoleinfo); +// if (!consoleinfo.st_uid) +// { +// sleep(1); +// continue; +// } +// else if ((GETJACKSTATUS() & 0x80000000) != 0x80000000) +// return unplugged(); +// +// if (awake) awake = false; +// //get current locale settings +// NSString *locale = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleLocale"]; +// //load localized strings +// NSDictionary* CurDict = [l10nDict objectForKey:locale]; +// NSMutableDictionary* Merged = dlgText.mutableCopy; +// [Merged addEntriesFromDictionary: CurDict]; +// //display dialog +// CFUserNotificationDisplayAlert( +// 0, // CFTimeInterval timeout +// kCFUserNotificationNoteAlertLevel, // CFOptionFlags flags +// iconUrl, // CFURLRef iconURL (file location URL) +// NULL, // CFURLRef soundURL (unused) +// NULL, // CFURLRef localizationURL +// GET_CFSTR_FROM_DICT(Merged, @"dialogTitle"), //CFStringRef alertHeader +// GET_CFSTR_FROM_DICT(Merged, @"dialogMsg"), //CFStringRef alertMessage +// GET_CFSTR_FROM_DICT(Merged, @"btnHeadphone"), //CFStringRef defaultButtonTitle +// NULL, // GET_CFSTR_FROM_DICT(Merged, @"btnLinein"), //CFStringRef alternateButtonTitle +// //GET_CFSTR_FROM_DICT(Merged, @"btnCancel"), //CFStringRef alternateButtonTitle +// GET_CFSTR_FROM_DICT(Merged, @"btnHeadset"), //CFStringRef otherButtonTitle +// &responsecode // CFOptionFlags *responseFlags +// ); +// break; +// } + + if ((GETJACKSTATUS() & 0x80000000) != 0x80000000) + return unplugged(); + + /* Responses are of this format: + kCFUserNotificationDefaultResponse = 0, + kCFUserNotificationAlternateResponse = 1, + kCFUserNotificationOtherResponse = 2, + kCFUserNotificationCancelResponse = 3 + */ + + switch (responsecode) + { + case kCFUserNotificationDefaultResponse: + fprintf(stderr, "Headphones selected.\n"); + return headphones(); + break; + case kCFUserNotificationAlternateResponse: + fprintf(stderr, "Line-In selected.\n"); + return linein(); + //Cancel + //fprintf(stderr, "Cancelled.\n"); + //return 0; // Maintain current state + break; + case kCFUserNotificationOtherResponse: + fprintf(stderr, "Headset selected.\n"); + return headsetcheck(); + break; + default: + fprintf(stderr, "Cancelled.\n"); + // return unplugged(); // This was originally meant to reset the jack state to "unplugged," but "maintaining current state" is more intuitive + return 0; // Maintain current state + break; + } + + return 0; +} + +// +// Respect OS signals +// + +void sigHandler(int signo) +{ + fprintf(stderr, "\nsigHandler: Received signal %d\n", signo); // Technically this print is not async-safe, but so far haven't run into any issues + switch (signo) + { + // Need to be sure object gets released correctly on any kind of quit + // notification, otherwise the program's left still running! + case SIGINT: // CTRL + c or Break key + case SIGTERM: // Shutdown/Restart + case SIGHUP: // "Hang up" (legacy) + case SIGKILL: // Kill + case SIGTSTP: // Close terminal from x button + run = false; + break; // SIGTERM, SIGINT mean we must quit, so do it gracefully + default: + break; + } +} + +//Codec fixup, invoked when boot/wake +void alcInit() +{ + fprintf(stderr, "Init codec.\n"); + switch (codecID) + { + case 0x10ec0256: + if (indexOf(xps13SubDev, 4, subDevice) == -1 || subVendor != 0x1028) + goto ALC255_COMMON; + fprintf(stderr, "Fix XPS 13.\n"); + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x25)); + VerbCommand(HDA_VERB(0x21, AC_VERB_SET_UNSOLICITED_ENABLE, 0x83)); + //ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE + VerbCommand(HDA_VERB(0x20, AC_VERB_SET_COEF_INDEX, 0x36)); + VerbCommand(HDA_VERB(0x20, AC_VERB_SET_PROC_COEF, 0x1737)); + //ALC255_FIXUP_DELL1_MIC_NO_PRESENCE -> ALC255_FIXUP_HEADSET_MODE -> alc255_set_default_jack_type + WRITE_COEF(0x1b, 0x884b); + WRITE_COEF(0x45, 0xd089); + WRITE_COEF(0x1b, 0x084b); + WRITE_COEF(0x46, 0x0004); + WRITE_COEF(0x1b, 0x0c4b); + break; + case 0x10ec0295: + WRITE_COEFEX(0x4a, 0x8000, 1 << 15); + WRITE_COEFEX(0x4a, 0x8000, 0 << 15); + goto ALC255_COMMON; + case 0x10ec0255: + ALC255_COMMON: + VerbCommand(HDA_VERB(0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24)); + VerbCommand(HDA_VERB(0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20)); + VerbCommand(HDA_VERB(0x21, AC_VERB_SET_UNSOLICITED_ENABLE, 0x83)); + break; + case 0x10ec0298: + VerbCommand(HDA_VERB(0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x22)); + VerbCommand(HDA_VERB(0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x23)); + VerbCommand(HDA_VERB(0x21, AC_VERB_SET_UNSOLICITED_ENABLE, 0x83)); + break; + default: + break; + } +} + +// Sleep/Wake event callback function, calls the fixup function +void SleepWakeCallBack( void * refCon, io_service_t service, natural_t messageType, void * messageArgument ) +{ + switch ( messageType ) + { + case kIOMessageCanSystemSleep: + IOAllowPowerChange( root_port, (long)messageArgument ); + break; + case kIOMessageSystemWillSleep: + IOAllowPowerChange( root_port, (long)messageArgument ); + break; + case kIOMessageSystemWillPowerOn: + break; + case kIOMessageSystemHasPoweredOn: + while(run) + { + if (GETJACKSTATUS() != -1) + break; + usleep(250000); + } + printf( "Re-init codec...\n" ); + alcInit(); + awake = true; + break; + default: + break; + } +} + +// start cfrunloop that listen to wakeup event +void watcher(void) +{ + IONotificationPortRef notifyPortRef; + void* refCon = NULL; + root_port = IORegisterForSystemPower( refCon, ¬ifyPortRef, SleepWakeCallBack, ¬ifierObject ); + if ( root_port == 0 ) + { + printf("IORegisterForSystemPower failed\n"); + exit(1); + } + else + { + CFRunLoopAddSource( CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes ); + printf("Starting wakeup watcher\n"); + CFRunLoopRun(); + } +} + + +//Get onboard audio device info, adapted from DPCIManager +void getAudioID() +{ + codecID = 0, subVendor = 0, subDevice = 0; + io_service_t HDACodecFuncIOService; + io_service_t HDACodecDrvIOService; + io_service_t HDACodecDevIOService; + io_service_t HDACtrlIOService; + io_service_t pciDevIOService; + IORegistryEntryGetParentEntry(VerbIOService, kIOServicePlane, &HDACodecFuncIOService); //IOHDACodecFunction + IORegistryEntryGetParentEntry(HDACodecFuncIOService, kIOServicePlane, &HDACodecDrvIOService); //IOHDACodecDriver + IORegistryEntryGetParentEntry(HDACodecDrvIOService, kIOServicePlane, &HDACodecDevIOService); //IOHDACodecDevice + IORegistryEntryGetParentEntry(HDACodecDevIOService, kIOServicePlane, &HDACtrlIOService);//AppleHDAController + IORegistryEntryGetParentEntry(HDACtrlIOService, kIOServicePlane, &pciDevIOService);//HDEF + pciDevice *audio = [pciDevice create:pciDevIOService]; + codecID = [[pciDevice grabNumber:CFSTR("IOHDACodecVendorID") forService:HDACodecDevIOService] longValue] & 0xFFFFFFFF; + subVendor = audio.subVendor.intValue; + subDevice = audio.subDevice.intValue; + fprintf(stderr, "CodecID: 0x%lx\n", codecID); + fprintf(stderr, "subVendor: 0x%x\n", subVendor); + fprintf(stderr, "subDevice: 0x%x\n", subDevice); + IOObjectRelease(HDACodecFuncIOService); + IOObjectRelease(HDACodecDrvIOService); + IOObjectRelease(HDACodecDevIOService); + IOObjectRelease(HDACtrlIOService); + IOObjectRelease(pciDevIOService); + //[audio release]; +} + +// +// Main +// + +int main() +{ + fprintf(stderr, "Starting jack watcher.\n"); + //Allow only one instance + if (sem_open("XPS_ComboJack_Watcher", O_CREAT, 600, 1) == SEM_FAILED) + { + fprintf(stderr, "Another instance is already running!\n"); + return 1; + } + // Set up error handler + signal(SIGHUP, sigHandler); + signal(SIGTERM, sigHandler); + signal(SIGINT, sigHandler); + signal(SIGKILL, sigHandler); + signal(SIGTSTP, sigHandler); + + // Local variables + kern_return_t ServiceConnectionStatus; + int version; + //int nid, verb, param; + u32 jackstat; + //struct hda_verb_ioctl val; + + // Mac version of hda-verb + version = 0x2710; // Darwin + + // If this error appears, the program was compiled incorrectly + if (version < HDA_HWDEP_VERSION) { + fprintf(stderr, "Invalid version number 0x%x\n", version); + return 1; + } + + // Establish user-kernel connection + ServiceConnectionStatus = OpenServiceConnection(); + if (ServiceConnectionStatus != kIOReturnSuccess) + { + while ((ServiceConnectionStatus != kIOReturnSuccess) && run) + { + fprintf(stderr, "Error establshing IOService connection. Retrying in 1 second...\n"); + sleep (1); + ServiceConnectionStatus = OpenServiceConnection(); + } + } + + // Get audio device info, exit if no compatible device found + getAudioID(); + //long codecIDArr[3] = {0x10ec0256, 0x10ec0255, 0x10ec0298}; + if (indexOf_L(codecIDArr, 4, codecID) == -1 || ! subVendor || !subDevice) + { + fprintf(stderr, "No compatible audio device found! Exit now.\n"); + return 1; + } + + //alc256 init + alcInit(); + //start a new thread that waits for wakeup event + pthread_t watcher_id; + if (pthread_create(&watcher_id,NULL,(void*)watcher,NULL)) + { + fprintf(stderr, "create pthread error!\n"); + return 1; + } + + //load ui resources + iconUrl = CFURLCreateWithString(NULL, CFSTR("file:///usr/local/share/ComboJack/Headphone.icns"), NULL); + if (!CFURLResourceIsReachable(iconUrl, NULL)) + iconUrl = NULL; + //NSData *l10nData = [NSData dataWithContentsOfFile:@"/usr/local/share/ComboJack/l10n.json"]; + /* + if(NSClassFromString(@"NSJSONSerialization")) + { + NSError *error = nil; + id l10nObj = [NSJSONSerialization + JSONObjectWithData:[NSData dataWithContentsOfFile:@"/usr/local/share/ComboJack/l10n.json"] + options:0 error:&error]; + if(!error && [l10nObj isKindOfClass:[NSDictionary class]]) + l10nDict = l10nObj; + } + */ + dlgText = [[NSDictionary alloc] initWithObjectsAndKeys: + @"Combo Jack Notification", @"dialogTitle", + @"What did you just plug in? (Press ESC to cancel)", @"dialogMsg", + @"Headphones", @"btnHeadphone", + @"Line-In", @"btnLinein", + @"Headset", @"btnHeadset", + @"Cancel", @"btnCancel", + nil]; + + // Set up jack monitor verb command + //nid = REALTEK_HP_OUT; + //verb = AC_VERB_GET_PIN_SENSE; + //param = 0x00; + + //fprintf(stderr, "nid = 0x%x, verb = 0x%x, param = 0x%x\n", nid, verb, param); + +// fprintf(stderr, "TEST Update Coef Command = 0x%x\n", UPDATE_COEF(0x4f, 0xfcc0, 0xd400)); + + // Properly format jack monitor verb command + //val.verb = HDA_VERB(nid, verb, param); + + // This is just a test send +// fprintf(stderr, "Verb Command = 0x%x\n", val.verb); +// val.res = VerbCommand(val.verb); +// fprintf(stderr, "Response = 0x%x\n", val.res); + int counter = 4; + + while (run) // Poll headphone jack state + { + jackstat = GETJACKSTATUS(); + if (jackstat == -1) // 0xFFFFFFFF means jack not ready yet + { + fprintf(stderr, "Jack not ready. Checking again in 1 second...\n"); + counter = 4; + } + else if ((jackstat & 0x80000000) == 0x80000000) + { + if (--counter < 0) + { + counter = 4; + fprintf(stderr, "Jack sense detected! Displaying menu...\n"); + if (CFPopUpMenu() == 0) + { + JackBehavior(); + } + else + { + break; + } + } + } + else + counter = 4; + + //if (awake) awake = false; + usleep(250*1000); // Sleep delay (seconds): use usleep for microseconds if fine-grained control is needed + } + + // All done here, clean up and exit safely + CloseServiceConnection(); + /* + IODeregisterForSystemPower(¬ifier); + IOServiceClose(rootPort); + IONotificationPortDestroy(notificationPort); + */ + fprintf(stderr, "Exiting safely!\n"); + + return 0; +} diff --git a/ComboJack_Source/Combo Jack/hda_hwdep.h b/ComboJack_Source/Combo Jack/hda_hwdep.h new file mode 100644 index 0000000..bb753f3 --- /dev/null +++ b/ComboJack_Source/Combo Jack/hda_hwdep.h @@ -0,0 +1,42 @@ +/* + * HWDEP Interface for HD-audio codec + * + * Copyright (c) 2007 Takashi Iwai + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Adapted from hda-verb from alsa-tools: +// https://www.alsa-project.org/main/index.php/Main_Page +// + +#ifndef __SOUND_HDA_HWDEP_H +#define __SOUND_HDA_HWDEP_H + +#define HDA_HWDEP_VERSION 0x2710 /* Darwin */ + +/* verb */ +#define HDA_REG_NID_SHIFT 20 +#define HDA_REG_VERB_SHIFT 8 +#define HDA_REG_VAL_SHIFT 0 +#define HDA_VERB(nid,verb,param) ((nid)<<20 | (verb)<<8 | (param)) + +struct hda_verb_ioctl { + u32 verb; /* HDA_VERB() */ + u32 res; /* response */ +}; + +#endif diff --git a/ComboJack_Source/Combo Jack/rt298.h b/ComboJack_Source/Combo Jack/rt298.h new file mode 100644 index 0000000..c4ce89c --- /dev/null +++ b/ComboJack_Source/Combo Jack/rt298.h @@ -0,0 +1,219 @@ +/* + * rt298.h -- RT298 ALSA SoC audio driver + * + * Copyright 2011 Realtek Microelectronics + * Author: Johnny Hsu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +// +// Very lightly adapted from the Linux kernel: +// https://github.com/torvalds/linux +// + +#ifndef __RT298_H__ +#define __RT298_H__ + +#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D) + +#define RT298_AUDIO_FUNCTION_GROUP 0x01 +#define RT298_DAC_OUT1 0x02 +#define RT298_DAC_OUT2 0x03 +#define RT298_DIG_CVT 0x06 +#define RT298_ADC_IN1 0x09 +#define RT298_ADC_IN2 0x08 +#define RT298_MIXER_IN 0x0b +#define RT298_MIXER_OUT1 0x0c +#define RT298_MIXER_OUT2 0x0d +#define RT298_DMIC1 0x12 +#define RT298_DMIC2 0x13 +#define RT298_SPK_OUT 0x14 // 0x17 for ALC3266 +#define RT298_MIC1 0x18 +#define RT298_LINE1 0x1a +#define RT298_BEEP 0x1d +#define RT298_SPDIF 0x1e +#define RT298_VENDOR_REGISTERS 0x20 +#define RT298_HP_OUT 0x21 +#define RT298_MIXER_IN1 0x22 +#define RT298_MIXER_IN2 0x23 +#define RT298_INLINE_CMD 0x55 + +#define RT298_SET_PIN_SFT 6 +#define RT298_SET_PIN_ENABLE 0x40 +#define RT298_SET_PIN_DISABLE 0 +#define RT298_SET_EAPD_HIGH 0x2 +#define RT298_SET_EAPD_LOW 0 + +#define RT298_MUTE_SFT 7 + +/* Verb commands */ +#define RT298_GET_PARAM(NID, PARAM) VERB_CMD(AC_VERB_PARAMETERS, NID, PARAM) +#define RT298_SET_POWER(NID) VERB_CMD(AC_VERB_SET_POWER_STATE, NID, 0) +#define RT298_SET_AUDIO_POWER RT298_SET_POWER(RT298_AUDIO_FUNCTION_GROUP) +#define RT298_SET_HPO_POWER RT298_SET_POWER(RT298_HP_OUT) +#define RT298_SET_SPK_POWER RT298_SET_POWER(RT298_SPK_OUT) +#define RT298_SET_DMIC1_POWER RT298_SET_POWER(RT298_DMIC1) +#define RT298_SPK_MUX\ + VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_SPK_OUT, 0) +#define RT298_HPO_MUX\ + VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_HP_OUT, 0) +#define RT298_ADC0_MUX\ + VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN1, 0) +#define RT298_ADC1_MUX\ + VERB_CMD(AC_VERB_SET_CONNECT_SEL, RT298_MIXER_IN2, 0) +#define RT298_SET_MIC1\ + VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_MIC1, 0) +#define RT298_SET_PIN_HPO\ + VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_HP_OUT, 0) +#define RT298_SET_PIN_SPK\ + VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPK_OUT, 0) +#define RT298_SET_PIN_DMIC1\ + VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_DMIC1, 0) +#define RT298_SET_PIN_SPDIF\ + VERB_CMD(AC_VERB_SET_PIN_WIDGET_CONTROL, RT298_SPDIF, 0) +#define RT298_SET_PIN_DIG_CVT\ + VERB_CMD(AC_VERB_SET_DIGI_CONVERT_1, RT298_DIG_CVT, 0) +#define RT298_SPK_EAPD\ + VERB_CMD(AC_VERB_SET_EAPD_BTLENABLE, RT298_SPK_OUT, 0) +#define RT298_SET_AMP_GAIN_HPO\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0) +#define RT298_SET_AMP_GAIN_ADC_IN1\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0) +#define RT298_SET_AMP_GAIN_ADC_IN2\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN2, 0) +#define RT298_GET_HP_SENSE\ + VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_HP_OUT, 0) +#define RT298_GET_MIC1_SENSE\ + VERB_CMD(AC_VERB_GET_PIN_SENSE, RT298_MIC1, 0) +#define RT298_SET_DMIC2_DEFAULT\ + VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_DMIC2, 0) +#define RT298_SET_SPDIF_DEFAULT\ + VERB_CMD(AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, RT298_SPDIF, 0) +#define RT298_DACL_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0xa000) +#define RT298_DACR_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_DAC_OUT1, 0x9000) +#define RT298_ADCL_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x6000) +#define RT298_ADCR_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_ADC_IN1, 0x5000) +#define RT298_MIC_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIC1, 0x7000) +#define RT298_SPOL_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0xa000) +#define RT298_SPOR_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_SPK_OUT, 0x9000) +#define RT298_HPOL_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0xa000) +#define RT298_HPOR_GAIN\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_HP_OUT, 0x9000) +#define RT298_F_DAC_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7000) +#define RT298_F_RECMIX_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_OUT1, 0x7100) +#define RT298_REC_MIC_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7000) +#define RT298_REC_I2S_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7100) +#define RT298_REC_LINE_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7200) +#define RT298_REC_BEEP_SWITCH\ + VERB_CMD(AC_VERB_SET_AMP_GAIN_MUTE, RT298_MIXER_IN, 0x7300) +#define RT298_DAC_FORMAT\ + VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_DAC_OUT1, 0) +#define RT298_ADC_FORMAT\ + VERB_CMD(AC_VERB_SET_STREAM_FORMAT, RT298_ADC_IN1, 0) +#define RT298_COEF_INDEX\ + VERB_CMD(AC_VERB_SET_COEF_INDEX, RT298_VENDOR_REGISTERS, 0) +#define RT298_PROC_COEF\ + VERB_CMD(AC_VERB_SET_PROC_COEF, RT298_VENDOR_REGISTERS, 0) +#define RT298_UNSOLICITED_INLINE_CMD\ + VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT298_INLINE_CMD, 0) +#define RT298_UNSOLICITED_HP_OUT\ + VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT298_HP_OUT, 0) +#define RT298_UNSOLICITED_MIC1\ + VERB_CMD(AC_VERB_SET_UNSOLICITED_ENABLE, RT298_MIC1, 0) + +/* Index registers */ +#define RT298_A_BIAS_CTRL1 0x01 +#define RT298_A_BIAS_CTRL2 0x02 +#define RT298_POWER_CTRL1 0x03 +#define RT298_A_BIAS_CTRL3 0x04 +#define RT298_D_FILTER_CTRL 0x05 +#define RT298_POWER_CTRL2 0x08 +#define RT298_I2S_CTRL1 0x09 +#define RT298_I2S_CTRL2 0x0a +#define RT298_CLK_DIV 0x0b +#define RT298_DC_GAIN 0x0d +#define RT298_POWER_CTRL3 0x0f +#define RT298_MIC1_DET_CTRL 0x19 +#define RT298_MISC_CTRL1 0x20 +#define RT298_IRQ_CTRL 0x33 +#define RT298_WIND_FILTER_CTRL 0x46 +#define RT298_PLL_CTRL1 0x49 +#define RT298_VAD_CTRL 0x4e +#define RT298_CBJ_CTRL1 0x4f +#define RT298_CBJ_CTRL2 0x50 +#define RT298_PLL_CTRL 0x63 +#define RT298_DEPOP_CTRL1 0x66 +#define RT298_DEPOP_CTRL2 0x67 +#define RT298_DEPOP_CTRL3 0x68 +#define RT298_DEPOP_CTRL4 0x69 +#define RT298_IRQ_FLAG_CTRL 0x7c + +/* SPDIF (0x06) */ +#define RT298_SPDIF_SEL_SFT 0 +#define RT298_SPDIF_SEL_PCM0 0 +#define RT298_SPDIF_SEL_PCM1 1 +#define RT298_SPDIF_SEL_SPOUT 2 +#define RT298_SPDIF_SEL_PP 3 + +/* RECMIX (0x0b) */ +#define RT298_M_REC_BEEP_SFT 0 +#define RT298_M_REC_LINE1_SFT 1 +#define RT298_M_REC_MIC1_SFT 2 +#define RT298_M_REC_I2S_SFT 3 + +/* Front (0x0c) */ +#define RT298_M_FRONT_DAC_SFT 0 +#define RT298_M_FRONT_REC_SFT 1 + +/* SPK-OUT (0x14) */ +#define RT298_M_SPK_MUX_SFT 14 +#define RT298_SPK_SEL_MASK 0x1 +#define RT298_SPK_SEL_SFT 0 +#define RT298_SPK_SEL_F 0 +#define RT298_SPK_SEL_S 1 + +/* HP-OUT (0x21) */ +#define RT298_M_HP_MUX_SFT 14 +#define RT298_HP_SEL_MASK 0x1 +#define RT298_HP_SEL_SFT 0 +#define RT298_HP_SEL_F 0 +#define RT298_HP_SEL_S 1 + +/* ADC (0x22) (0x23) */ +#define RT298_ADC_SEL_MASK 0x7 +#define RT298_ADC_SEL_SFT 0 +#define RT298_ADC_SEL_SURR 0 +#define RT298_ADC_SEL_FRONT 1 +#define RT298_ADC_SEL_DMIC 2 +#define RT298_ADC_SEL_BEEP 4 +#define RT298_ADC_SEL_LINE1 5 +#define RT298_ADC_SEL_I2S 6 +#define RT298_ADC_SEL_MIC1 7 + +#define RT298_SCLK_S_MCLK 0 +#define RT298_SCLK_S_PLL 1 + +enum { + RT298_AIF1, + RT298_AIF2, + RT298_AIFS, +}; + +#endif /* __RT298_H__ */ + diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.pbxproj b/ComboJack_Source/ComboJack.xcodeproj/project.pbxproj new file mode 100644 index 0000000..03c8082 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/project.pbxproj @@ -0,0 +1,278 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3D086A6C21BD498700FFD44C /* PCI.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D086A6A21BD498700FFD44C /* PCI.m */; }; + CB3D2DA81F0DFEDE00CF6EBA /* hda-verb.m in Sources */ = {isa = PBXBuildFile; fileRef = CB3D2DA71F0DFEDE00CF6EBA /* hda-verb.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3D086A6A21BD498700FFD44C /* PCI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PCI.m; sourceTree = ""; }; + 3D086A6B21BD498700FFD44C /* PCI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCI.h; sourceTree = ""; }; + 3D2BE1A921BD50C300FA7A55 /* Tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tables.h; sourceTree = ""; }; + CB3D2DA71F0DFEDE00CF6EBA /* hda-verb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "hda-verb.m"; sourceTree = ""; }; + CB3D58431F0A7DE000F741BA /* ComboJack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ComboJack; sourceTree = BUILT_PRODUCTS_DIR; }; + CB3D58641F0A835500F741BA /* hda_hwdep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hda_hwdep.h; sourceTree = ""; }; + CB3D58671F0B219000F741BA /* rt298.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rt298.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CB3D58401F0A7DE000F741BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + CB3D583A1F0A7DE000F741BA = { + isa = PBXGroup; + children = ( + CB3D58451F0A7DE000F741BA /* ComboJack */, + CB3D58441F0A7DE000F741BA /* Products */, + ); + sourceTree = ""; + }; + CB3D58441F0A7DE000F741BA /* Products */ = { + isa = PBXGroup; + children = ( + CB3D58431F0A7DE000F741BA /* ComboJack */, + ); + name = Products; + sourceTree = ""; + }; + CB3D58451F0A7DE000F741BA /* ComboJack */ = { + isa = PBXGroup; + children = ( + 3D2BE1A921BD50C300FA7A55 /* Tables.h */, + 3D086A6B21BD498700FFD44C /* PCI.h */, + 3D086A6A21BD498700FFD44C /* PCI.m */, + CB3D2DA71F0DFEDE00CF6EBA /* hda-verb.m */, + CB3D58671F0B219000F741BA /* rt298.h */, + CB3D58641F0A835500F741BA /* hda_hwdep.h */, + ); + name = ComboJack; + path = "Combo Jack"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + CB3D58421F0A7DE000F741BA /* ComboJack */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB3D584A1F0A7DE000F741BA /* Build configuration list for PBXNativeTarget "ComboJack" */; + buildPhases = ( + CB3D583F1F0A7DE000F741BA /* Sources */, + CB3D58401F0A7DE000F741BA /* Frameworks */, + 3DF6155621AAD40A0057F150 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ComboJack; + productName = "Combo Jack"; + productReference = CB3D58431F0A7DE000F741BA /* ComboJack */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CB3D583B1F0A7DE000F741BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = VerbStub; + TargetAttributes = { + CB3D58421F0A7DE000F741BA = { + CreatedOnToolsVersion = 8.3.3; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = CB3D583E1F0A7DE000F741BA /* Build configuration list for PBXProject "ComboJack" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + ); + mainGroup = CB3D583A1F0A7DE000F741BA; + productRefGroup = CB3D58441F0A7DE000F741BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CB3D58421F0A7DE000F741BA /* ComboJack */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3DF6155621AAD40A0057F150 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n#cd \"${TARGET_BUILD_DIR}\"\n#cp -f ComboJack ../../../ComboJack_Installer/\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CB3D583F1F0A7DE000F741BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D086A6C21BD498700FFD44C /* PCI.m in Sources */, + CB3D2DA81F0DFEDE00CF6EBA /* hda-verb.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + CB3D58481F0A7DE000F741BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + CB3D58491F0A7DE000F741BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + CB3D584B1F0A7DE000F741BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CB3D584C1F0A7DE000F741BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + CB3D583E1F0A7DE000F741BA /* Build configuration list for PBXProject "ComboJack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB3D58481F0A7DE000F741BA /* Debug */, + CB3D58491F0A7DE000F741BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB3D584A1F0A7DE000F741BA /* Build configuration list for PBXNativeTarget "ComboJack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB3D584B1F0A7DE000F741BA /* Debug */, + CB3D584C1F0A7DE000F741BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CB3D583B1F0A7DE000F741BA /* Project object */; +} diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..bd08605 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..0599024 Binary files /dev/null and b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ff07a0b Binary files /dev/null and b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/saintno.xcuserdatad/UserInterfaceState.xcuserstate b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/saintno.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..16342f0 Binary files /dev/null and b/ComboJack_Source/ComboJack.xcodeproj/project.xcworkspace/xcuserdata/saintno.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcshareddata/xcschemes/ComboJack.xcscheme b/ComboJack_Source/ComboJack.xcodeproj/xcshareddata/xcschemes/ComboJack.xcscheme new file mode 100644 index 0000000..3ee3287 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcshareddata/xcschemes/ComboJack.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/Combo Jack.xcscheme b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/Combo Jack.xcscheme new file mode 100644 index 0000000..6b159ef --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/Combo Jack.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..55e6d36 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + Combo Jack.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + CB3D58421F0A7DE000F741BA + + primary + + + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..6b5623b --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + ComboJack.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/saintno.xcuserdatad/xcschemes/xcschememanagement.plist b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/saintno.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..f35d380 --- /dev/null +++ b/ComboJack_Source/ComboJack.xcodeproj/xcuserdata/saintno.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + ComboJack.xcscheme_^#shared#^_ + + orderHint + 0 + + + SuppressBuildableAutocreation + + CB3D58421F0A7DE000F741BA + + primary + + + + + diff --git a/ComboJack_Source/Headphone.icns b/ComboJack_Source/Headphone.icns new file mode 100644 index 0000000..0e29d9d Binary files /dev/null and b/ComboJack_Source/Headphone.icns differ diff --git a/ComboJack_Source/LICENSE b/ComboJack_Source/LICENSE new file mode 100644 index 0000000..c8ee2c2 --- /dev/null +++ b/ComboJack_Source/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + handles EAPD state updating for power-managed HDA codecs + Copyright (C) 2013 Dolnor + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ComboJack_Source/build.sh b/ComboJack_Source/build.sh new file mode 100644 index 0000000..ed40b72 --- /dev/null +++ b/ComboJack_Source/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +cd `dirname $0` + +xcodebuild -configuration Release || exit 1 +rm -f ../ComboJack_Installer/ComboJack +rm -f ../ComboJack_Installer/Headphone.icns +rm -f ../ComboJack_Installer/l10n.json +cp -f build/Release/ComboJack ../ComboJack_Installer/ +cp -f ./Headphone.icns ../ComboJack_Installer/ +cp -f ./l10n.json ../ComboJack_Installer/ +#exec ./build/Release/ComboJack +rm -rf ./build +exec bash ../ComboJack_Installer/install.sh diff --git a/ComboJack_Source/l10n.json b/ComboJack_Source/l10n.json new file mode 100644 index 0000000..2fc5550 --- /dev/null +++ b/ComboJack_Source/l10n.json @@ -0,0 +1,42 @@ +{ + "zh_CN": { + "dialogTitle" : "耳机接入通知", + "dialogMsg" : "请选择接入的设备类型(按ESC键取消)", + "btnHeadphone" : "耳机", + "btnLinein" : "线路输入", + "btnHeadset" : "耳麦", + "btnCancel" : "取消" + }, + "en_US": { + "dialogTitle" : "Combo Jack Notification", + "dialogMsg" : "What did you just plug in? (Press ESC to cancel)", + "btnHeadphone" : "Headphones", + "btnLinein" : "Line-In", + "btnHeadset" : "Headset", + "btnCancel" : "Cancel" + }, + "ru_RU": { + "dialogTitle" : "Combo Jack Notification", + "dialogMsg" : "Какое устройство было подключено? (ESC для отмены)", + "btnHeadphone" : "Наушники", + "btnLinein" : "Линейный вход", + "btnHeadset" : "Гарнитура", + "btnCancel" : "Отмена" + }, + "ru_UA": { + "dialogTitle" : "Combo Jack Notification", + "dialogMsg" : "Какое устройство было подключено? (ESC для отмены)", + "btnHeadphone" : "Наушники", + "btnLinein" : "Линейный вход", + "btnHeadset" : "Гарнитура", + "btnCancel" : "Отмена" + }, + "uk_UA": { + "dialogTitle" : "Combo Jack Notification", + "dialogMsg" : "Який пристрій було підключено? (ESC для скасування)", + "btnHeadphone" : "Навушники", + "btnLinein" : "Лінійний вхід", + "btnHeadset" : "Гарнітура", + "btnCancel" : "Скасувати" + } +} diff --git a/VerbStub_Source/LICENSE b/VerbStub_Source/LICENSE new file mode 100644 index 0000000..c8ee2c2 --- /dev/null +++ b/VerbStub_Source/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + handles EAPD state updating for power-managed HDA codecs + Copyright (C) 2013 Dolnor + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/VerbStub_Source/VerbStub.xcodeproj/project.pbxproj b/VerbStub_Source/VerbStub.xcodeproj/project.pbxproj new file mode 100644 index 0000000..49da079 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/project.pbxproj @@ -0,0 +1,435 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + CB3C1C3F1F08A6B500F26D79 /* hda-verb.c in Sources */ = {isa = PBXBuildFile; fileRef = CB3C1C3E1F08A6B500F26D79 /* hda-verb.c */; }; + CB3C1C581F0967CA00F26D79 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB3C1C561F08AA4300F26D79 /* IOKit.framework */; }; + CB3C1C5A1F0967D200F26D79 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB3C1C521F08AA3600F26D79 /* CoreFoundation.framework */; }; + CB3C1C7A1F0979D900F26D79 /* VerbStub.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CB3C1C791F0979D900F26D79 /* VerbStub.hpp */; }; + CB3C1C7C1F0979D900F26D79 /* VerbStub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB3C1C7B1F0979D900F26D79 /* VerbStub.cpp */; }; + CB3C1C831F0979E900F26D79 /* IntelHDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB3C1C811F0979E900F26D79 /* IntelHDA.cpp */; }; + CB3C1C841F0979E900F26D79 /* IntelHDA.h in Headers */ = {isa = PBXBuildFile; fileRef = CB3C1C821F0979E900F26D79 /* IntelHDA.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + CB3C1C361F08A67000F26D79 /* hda-verb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "hda-verb"; sourceTree = BUILT_PRODUCTS_DIR; }; + CB3C1C3D1F08A6B500F26D79 /* hda_hwdep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hda_hwdep.h; sourceTree = ""; }; + CB3C1C3E1F08A6B500F26D79 /* hda-verb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "hda-verb.c"; sourceTree = ""; }; + CB3C1C521F08AA3600F26D79 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + CB3C1C541F08AA3D00F26D79 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; }; + CB3C1C561F08AA4300F26D79 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + CB3C1C771F0979D800F26D79 /* VerbStub.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VerbStub.kext; sourceTree = BUILT_PRODUCTS_DIR; }; + CB3C1C791F0979D900F26D79 /* VerbStub.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VerbStub.hpp; sourceTree = ""; }; + CB3C1C7B1F0979D900F26D79 /* VerbStub.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VerbStub.cpp; sourceTree = ""; }; + CB3C1C7D1F0979D900F26D79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CB3C1C811F0979E900F26D79 /* IntelHDA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntelHDA.cpp; sourceTree = ""; }; + CB3C1C821F0979E900F26D79 /* IntelHDA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntelHDA.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CB3C1C331F08A67000F26D79 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CB3C1C5A1F0967D200F26D79 /* CoreFoundation.framework in Frameworks */, + CB3C1C581F0967CA00F26D79 /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB3C1C731F0979D800F26D79 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + CB3C1C071F08A20200F26D79 = { + isa = PBXGroup; + children = ( + CB3C1C371F08A67100F26D79 /* hda_verb */, + CB3C1C781F0979D900F26D79 /* VerbStub */, + CB3C1C121F08A20200F26D79 /* Products */, + CB3C1C511F08AA3600F26D79 /* Frameworks */, + ); + sourceTree = ""; + }; + CB3C1C121F08A20200F26D79 /* Products */ = { + isa = PBXGroup; + children = ( + CB3C1C361F08A67000F26D79 /* hda-verb */, + CB3C1C771F0979D800F26D79 /* VerbStub.kext */, + ); + name = Products; + sourceTree = ""; + }; + CB3C1C371F08A67100F26D79 /* hda_verb */ = { + isa = PBXGroup; + children = ( + CB3C1C3D1F08A6B500F26D79 /* hda_hwdep.h */, + CB3C1C3E1F08A6B500F26D79 /* hda-verb.c */, + ); + name = hda_verb; + path = "hda-verb"; + sourceTree = ""; + }; + CB3C1C511F08AA3600F26D79 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CB3C1C561F08AA4300F26D79 /* IOKit.framework */, + CB3C1C541F08AA3D00F26D79 /* Kernel.framework */, + CB3C1C521F08AA3600F26D79 /* CoreFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + CB3C1C781F0979D900F26D79 /* VerbStub */ = { + isa = PBXGroup; + children = ( + CB3C1C811F0979E900F26D79 /* IntelHDA.cpp */, + CB3C1C821F0979E900F26D79 /* IntelHDA.h */, + CB3C1C791F0979D900F26D79 /* VerbStub.hpp */, + CB3C1C7B1F0979D900F26D79 /* VerbStub.cpp */, + CB3C1C7D1F0979D900F26D79 /* Info.plist */, + ); + path = VerbStub; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + CB3C1C741F0979D800F26D79 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CB3C1C7A1F0979D900F26D79 /* VerbStub.hpp in Headers */, + CB3C1C841F0979E900F26D79 /* IntelHDA.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + CB3C1C351F08A67000F26D79 /* hda-verb */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB3C1C3A1F08A67100F26D79 /* Build configuration list for PBXNativeTarget "hda-verb" */; + buildPhases = ( + CB3C1C321F08A67000F26D79 /* Sources */, + CB3C1C331F08A67000F26D79 /* Frameworks */, + 3DF6155721AAD4BA0057F150 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "hda-verb"; + productName = "hda-verb"; + productReference = CB3C1C361F08A67000F26D79 /* hda-verb */; + productType = "com.apple.product-type.tool"; + }; + CB3C1C761F0979D800F26D79 /* VerbStub */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB3C1C7E1F0979D900F26D79 /* Build configuration list for PBXNativeTarget "VerbStub" */; + buildPhases = ( + CB3C1C721F0979D800F26D79 /* Sources */, + CB3C1C731F0979D800F26D79 /* Frameworks */, + CB3C1C741F0979D800F26D79 /* Headers */, + CB3C1C751F0979D800F26D79 /* Resources */, + 3DF6155821AAD4DB0057F150 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = VerbStub; + productName = VerbStub; + productReference = CB3C1C771F0979D800F26D79 /* VerbStub.kext */; + productType = "com.apple.product-type.kernel-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CB3C1C081F08A20200F26D79 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = VerbStub; + TargetAttributes = { + CB3C1C351F08A67000F26D79 = { + CreatedOnToolsVersion = 8.3.3; + ProvisioningStyle = Automatic; + }; + CB3C1C761F0979D800F26D79 = { + CreatedOnToolsVersion = 8.3.3; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = CB3C1C0B1F08A20200F26D79 /* Build configuration list for PBXProject "VerbStub" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = CB3C1C071F08A20200F26D79; + productRefGroup = CB3C1C121F08A20200F26D79 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CB3C1C351F08A67000F26D79 /* hda-verb */, + CB3C1C761F0979D800F26D79 /* VerbStub */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + CB3C1C751F0979D800F26D79 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3DF6155721AAD4BA0057F150 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncd \"${TARGET_BUILD_DIR}\"\ncp -f hda-verb ../../../ComboJack_Installer/\n"; + }; + 3DF6155821AAD4DB0057F150 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncd \"${TARGET_BUILD_DIR}\"\ncp -rf VerbStub.kext ../../../ComboJack_Installer/\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CB3C1C321F08A67000F26D79 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB3C1C3F1F08A6B500F26D79 /* hda-verb.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB3C1C721F0979D800F26D79 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB3C1C831F0979E900F26D79 /* IntelHDA.cpp in Sources */, + CB3C1C7C1F0979D900F26D79 /* VerbStub.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + CB3C1C171F08A20200F26D79 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + CB3C1C181F08A20200F26D79 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + CB3C1C3B1F08A67100F26D79 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + CB3C1C3C1F08A67100F26D79 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + CB3C1C7F1F0979D900F26D79 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1.0.3; + INFOPLIST_FILE = VerbStub/Info.plist; + MODULE_NAME = com.XPS.VerbStub; + MODULE_VERSION = 1.0.3; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wno-inconsistent-missing-override", + ); + PRODUCT_BUNDLE_IDENTIFIER = XPS.VerbStub; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = kext; + }; + name = Debug; + }; + CB3C1C801F0979D900F26D79 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1.0.3; + INFOPLIST_FILE = VerbStub/Info.plist; + MODULE_NAME = com.XPS.VerbStub; + MODULE_VERSION = 1.0.3; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-Wno-inconsistent-missing-override", + ); + PRODUCT_BUNDLE_IDENTIFIER = XPS.VerbStub; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = kext; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + CB3C1C0B1F08A20200F26D79 /* Build configuration list for PBXProject "VerbStub" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB3C1C171F08A20200F26D79 /* Debug */, + CB3C1C181F08A20200F26D79 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB3C1C3A1F08A67100F26D79 /* Build configuration list for PBXNativeTarget "hda-verb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB3C1C3B1F08A67100F26D79 /* Debug */, + CB3C1C3C1F08A67100F26D79 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB3C1C7E1F0979D900F26D79 /* Build configuration list for PBXNativeTarget "VerbStub" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB3C1C7F1F0979D900F26D79 /* Debug */, + CB3C1C801F0979D900F26D79 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = CB3C1C081F08A20200F26D79 /* Project object */; +} diff --git a/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..f05e032 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..f2a10ad Binary files /dev/null and b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/karl.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..28b1ef0 Binary files /dev/null and b/VerbStub_Source/VerbStub.xcodeproj/project.xcworkspace/xcuserdata/ling.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/VerbStub.xcscheme b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/VerbStub.xcscheme new file mode 100644 index 0000000..2a9d2b7 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/VerbStub.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/hda-verb.xcscheme b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/hda-verb.xcscheme new file mode 100644 index 0000000..62f13a3 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/hda-verb.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..2af3065 --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/karl.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,47 @@ + + + + + SchemeUserState + + VerbStub.xcscheme + + orderHint + 0 + + hda-verb.xcscheme + + orderHint + 1 + + + SuppressBuildableAutocreation + + CB3C1C101F08A20200F26D79 + + primary + + + CB3C1C2A1F08A5D200F26D79 + + primary + + + CB3C1C351F08A67000F26D79 + + primary + + + CB3C1C441F08A73100F26D79 + + primary + + + CB3C1C761F0979D800F26D79 + + primary + + + + + diff --git a/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..56ea01b --- /dev/null +++ b/VerbStub_Source/VerbStub.xcodeproj/xcuserdata/ling.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,19 @@ + + + + + SchemeUserState + + VerbStub.xcscheme_^#shared#^_ + + orderHint + 1 + + hda-verb.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/VerbStub_Source/VerbStub/Info.plist b/VerbStub_Source/VerbStub/Info.plist new file mode 100644 index 0000000..df5a92f --- /dev/null +++ b/VerbStub_Source/VerbStub/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + ${MODULE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + KEXT + CFBundleShortVersionString + ${MODULE_VERSION} + CFBundleVersion + ${MODULE_VERSION} + IOKitPersonalities + + VerbStubResidency + + CFBundleIdentifier + ${MODULE_NAME} + IOClass + VerbStubResidency + IOMatchCategory + VerbStubResidency + IOProviderClass + IOResources + + VerbStub + + CFBundleIdentifier + ${MODULE_NAME} + IOClass + com_XPS_VerbStub + IOProviderClass + IOHDACodecFunction + IOMatchCategory + com_XPS_VerbStub + IOUserClientClass + VerbStubUserClient + + + NSHumanReadableCopyright + Copyright © 2017 VerbStub. All rights reserved. + OSBundleLibraries + + com.apple.iokit.IOPCIFamily + 2.9 + com.apple.kpi.iokit + 16.6 + com.apple.kpi.libkern + 16.6 + + + diff --git a/VerbStub_Source/VerbStub/IntelHDA.cpp b/VerbStub_Source/VerbStub/IntelHDA.cpp new file mode 100644 index 0000000..7493ac0 --- /dev/null +++ b/VerbStub_Source/VerbStub/IntelHDA.cpp @@ -0,0 +1,429 @@ +/* + * Released under "The GNU General Public License (GPL-2.0)" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +// +// Adapted from CodecCommander: +// https://github.com/Dolnor/EAPD-Codec-Commander +// + +#include "IntelHDA.h" + +#define kIntelVendorID 0x8086 +#define kIntelRegTCSEL 0x44 + +static IOPCIDevice* getPCIDevice(IORegistryEntry* registryEntry) +{ + IOPCIDevice* result = NULL; + while (registryEntry) + { + result = OSDynamicCast(IOPCIDevice, registryEntry); + if (result) + break; + registryEntry = registryEntry->getParentEntry(gIOServicePlane); + } + return result; +} + +static UInt32 getPropertyValue(IORegistryEntry* registryEntry, const char* propertyName) +{ + UInt32 result = -1; + while (registryEntry) + { + if (OSNumber* value = OSDynamicCast(OSNumber, registryEntry->getProperty(propertyName))) + { + result = value->unsigned32BitValue(); + break; + } + registryEntry = registryEntry->getParentEntry(gIOServicePlane); + } + return result; +} + +IntelHDA::IntelHDA(IOService* provider, HDACommandMode commandMode) +{ + mCommandMode = commandMode; + mDevice = getPCIDevice(provider); + + mCodecVendorId = getPropertyValue(provider, kCodecVendorID); + mCodecGroupType = getPropertyValue(provider, kCodecFuncGroupType); + mCodecAddress = getPropertyValue(provider, kCodecAddress); + mCodecSubsystemId = getPropertyValue(provider, kCodecSubsystemID); + mCodecRevisionId = getPropertyValue(provider, kCodecRevisionID); + + // defaults for VoodooHDA... + if (0xFF == mCodecGroupType) mCodecGroupType = 1; + if (0xFF == mCodecAddress) mCodecAddress = 0; +} + +IntelHDA::~IntelHDA() +{ + OSSafeReleaseNULL(mMemoryMap); +} + +bool IntelHDA::initialize() +{ + DebugLog("IntelHDA::initialize\n"); + + if (mDevice == NULL) + { + AlwaysLog("mDevice is NULL in IntelHDA::initialize\n"); + return false; + } + if (mDevice->getDeviceMemoryCount() == 0) + { + AlwaysLog("getDeviceMemoryCount returned 0 in IntelHDA::initialize\n"); + return false; + } + if (mCodecAddress == 0xFF) + { + AlwaysLog("mCodecAddress is 0xFF in IntelHDA::initialize\n"); + return false; + } + if (mCodecGroupType != HDA_TYPE_AFG) + { + DebugLog("mCodecGroupType is %d (must be 1) in IntelHDA::initialize\n", mCodecGroupType); + return false; + } + + mDevice->setMemoryEnable(true); + + mDeviceMemory = mDevice->getDeviceMemoryWithIndex(0); + + if (mDeviceMemory == NULL) + { + AlwaysLog("Failed to access device memory.\n"); + return false; + } + + DebugLog("Device memory @ 0x%08llx, size 0x%08llx\n", mDeviceMemory->getPhysicalAddress(), mDeviceMemory->getLength()); + + mMemoryMap = mDeviceMemory->map(); + + if (mMemoryMap == NULL) + { + AlwaysLog("Failed to map device memory.\n"); + return false; + } + + DebugLog("Memory mapped at @ 0x%08llx\n", mMemoryMap->getVirtualAddress()); + + mRegMap = (pHDA_REG)mMemoryMap->getVirtualAddress(); + + char devicePath[1024]; + int pathLen = sizeof(devicePath); + bzero(devicePath, sizeof(devicePath)); + + uint32_t deviceInfo = mDevice->configRead32(0); + + if (mDevice->getPath(devicePath, &pathLen, gIOServicePlane)) + AlwaysLog("Evaluating device \"%s\" [%04x:%04x].\n", + devicePath, + deviceInfo & 0xFFFF, + deviceInfo >> 16); + + // Note: Must reset the codec here for getVendorId to work. + // If the computer is restarted when the codec is in fugue state (D3cold), + // it will not respond without the Double Function Group Reset. + if (mCodecVendorId == -1 && this->getVendorId() == 0xFFFF) + this->resetCodec(); + + if (mRegMap->VMAJ == 1 && mRegMap->VMIN == 0 && this->getVendorId() != 0xFFFF) + { + UInt16 vendor = this->getVendorId(); + UInt16 device = this->getDeviceId(); + UInt32 subsystem = this->getSubsystemId(); + UInt32 revision = this->getRevisionId(); + + if (mCodecVendorId == (UInt32)-1) + mCodecVendorId = (UInt32)vendor << 16 | device; + + // avoid logging HDMI audio (except in DEBUG build) as it is disabled anyway +#ifndef DEBUG + if (vendor != 0x8086) +#endif + { + AlwaysLog("....Codec Vendor ID: 0x%08x\n", mCodecVendorId); + AlwaysLog("....Codec Address: %d\n", mCodecAddress); + AlwaysLog("....Subsystem ID: 0x%08x\n", subsystem); + AlwaysLog("....Revision ID: 0x%08x\n", revision); + AlwaysLog("....PCI Sub ID: 0x%08x\n", getPCISubId()); + DebugLog("....Output Streams: %d\n", mRegMap->GCAP_OSS); + DebugLog("....Input Streams: %d\n", mRegMap->GCAP_ISS); + DebugLog("....Bidi Streams: %d\n", mRegMap->GCAP_BSS); + DebugLog("....Serial Data: %d\n", mRegMap->GCAP_NSDO); + DebugLog("....x64 Support: %d\n", mRegMap->GCAP_64OK); + DebugLog("....Codec Version: %d.%d\n", mRegMap->VMAJ, mRegMap->VMIN); + DebugLog("....Vendor ID: 0x%04x\n", vendor); + DebugLog("....Device ID: 0x%04x\n", device); + } + + return true; + } + + return false; +} + +void IntelHDA::resetCodec() +{ + /* + Reset is created by sending two Function Group resets, potentially separated + by an undefined number of idle frames, but no other valid commands. + This Function Group “Double” reset shall do a full initialization and reset + most settings to their power on defaults. + */ + + DebugLog("--> resetting codec\n"); + + UInt16 audioRoot = getAudioRoot(); + this->sendCommand(audioRoot, HDA_VERB_RESET, HDA_PARM_NULL); + IOSleep(1); + this->sendCommand(audioRoot, HDA_VERB_RESET, HDA_PARM_NULL); + IOSleep(220); // per-HDA spec, device must respond (D0) within 200ms + + // forcefully set power state to D3 + this->sendCommand(audioRoot, HDA_VERB_SET_PSTATE, HDA_PARM_PS_D3_HOT); + DebugLog("--> hda codec power restored\n"); +} + +void IntelHDA::applyIntelTCSEL() +{ + if (mDevice && mDevice->configRead16(kIOPCIConfigVendorID) == kIntelVendorID) + { + /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) + * TCSEL == Traffic Class Select Register, which sets PCI express QOS + * Ensuring these bits are 0 clears playback static on some HD Audio + * codecs. + * The PCI register TCSEL is defined in the Intel manuals. + */ + UInt8 value = mDevice->configRead8(kIntelRegTCSEL); + UInt8 newValue = value & ~0x07; + if (newValue != value) + { + mDevice->configWrite8(kIntelRegTCSEL, newValue); + DebugLog("Intel TCSEL: 0x%02x -> 0x%02x\n", value, newValue); + } + } +} + +UInt16 IntelHDA::getVendorId() +{ + if (mCodecVendorId == -1) + mCodecVendorId = this->sendCommand(0, HDA_VERB_GET_PARAM, HDA_PARM_VENDOR); + + return mCodecVendorId >> 16; +} + +UInt16 IntelHDA::getDeviceId() +{ + if (mCodecVendorId == -1) + mCodecVendorId = this->sendCommand(0, HDA_VERB_GET_PARAM, HDA_PARM_VENDOR); + + return mCodecVendorId & 0xFFFF; +} + +UInt16 IntelHDA::getAudioRoot() +{ + if (mAudioRoot == (UInt16)-1) + { + UInt32 nodes = this->sendCommand(0, HDA_VERB_GET_PARAM, HDA_PARM_NODECOUNT); + if (nodes != -1) + { + UInt16 start = nodes & 0xFF; + UInt16 end = start + ((nodes & 0xFF0000) >> 16); + for (UInt16 node = start; node < end; node++) + { + UInt32 type = this->sendCommand(node, HDA_VERB_GET_PARAM, HDA_PARM_FUNCGRP); + if ((type & 0xFF) == HDA_TYPE_AFG) + { + DebugLog("getAudioRoot found audio root = 0x%02x\n", node); + mAudioRoot = node; + break; + } + } + } + if (mAudioRoot == (UInt16)-1) + { + DebugLog("getAudioRoot failed to find audio root... using default root of 1\n"); + mAudioRoot = 1; + } + } + return mAudioRoot; +} + +UInt8 IntelHDA::getTotalNodes() +{ + if (mNodes == -1) + { + UInt16 audioRoot = getAudioRoot(); + mNodes = this->sendCommand(audioRoot, HDA_VERB_GET_PARAM, HDA_PARM_NODECOUNT); + // in the case of an invalid response, use zero + if (mNodes == -1) mNodes = 0; + } + return mNodes & 0x0000FF; +} + +UInt8 IntelHDA::getStartingNode() +{ + if (mNodes == -1) + { + UInt16 audioRoot = getAudioRoot(); + mNodes = this->sendCommand(audioRoot, HDA_VERB_GET_PARAM, HDA_PARM_NODECOUNT); + // in the case of an invalid response, use zero + if (mNodes == -1) mNodes = 0; + } + return (mNodes & 0xFF0000) >> 16; +} + +UInt32 IntelHDA::getSubsystemId() +{ + if (mCodecSubsystemId == -1) + { + UInt16 audioRoot = getAudioRoot(); + mCodecSubsystemId = this->sendCommand(audioRoot, HDA_VERB_GET_SUBSYSTEM_ID, HDA_PARM_NULL); + // in the case of an invalid response, use zero + if (mCodecSubsystemId == -1) mCodecSubsystemId = 0; + } + return mCodecSubsystemId; +} + +UInt32 IntelHDA::getPCISubId() +{ + UInt32 result = mDevice->configRead32(kIOPCIConfigSubSystemVendorID); + // flip words to be consistent with other 32-bit identifiers + return ((result & 0xFFFF) << 16) | result >> 16; +} + +UInt32 IntelHDA::getRevisionId() +{ + if (mCodecRevisionId == -1) + { + UInt16 audioRoot = getAudioRoot(); + mCodecRevisionId = this->sendCommand(audioRoot, HDA_VERB_GET_PARAM, HDA_PARM_REVISION); + // in the case of an invalid response, use zero + if (mCodecRevisionId == -1) mCodecRevisionId = 0; + } + return mCodecRevisionId; +} + +UInt32 IntelHDA::sendCommand(UInt8 nodeId, UInt16 verb, UInt8 payload) +{ + DebugLog("SendCommand: node 0x%02x, verb 0x%06x, payload 0x%02x.\n", nodeId, verb, payload); + return this->sendCommand((nodeId & 0xFF) << 20 | (verb & 0xFFF) << 8 | payload); +} + +UInt32 IntelHDA::sendCommand(UInt8 nodeId, UInt8 verb, UInt16 payload) +{ + DebugLog("SendCommand: node 0x%02x, verb 0x%02x, payload 0x%04x.\n", nodeId, verb, payload); + return this->sendCommand((nodeId & 0xFF) << 20 | (verb & 0xF) << 16 | payload); +} + +UInt32 IntelHDA::sendCommand(UInt32 command) +{ + UInt32 fullCommand = (mCodecAddress & 0xF) << 28 | (command & 0x0FFFFFFF); + + if (mDeviceMemory == NULL) + return -1; + + DebugLog("SendCommand: (w) --> 0x%08x\n", fullCommand); + + UInt32 response = -1; + + switch (mCommandMode) + { + case PIO: + response = this->executePIO(fullCommand); + break; + case DMA: + AlwaysLog("Unsupported command mode DMA requested.\n"); + response = -1; + break; + default: + response = -1; + break; + } + + DebugLog("SendCommand: (r) <-- 0x%08x\n", response); + + return response; +} + +UInt32 IntelHDA::executePIO(UInt32 command) +{ + UInt16 status; + + status = 0x1; // Busy status + + for (int i = 0; i < 1000; i++) + { + status = mRegMap->ICS; + + if (!HDA_ICS_IS_BUSY(status)) + break; + + ::IODelay(100); + } + + // HDA controller was not ready to receive PIO commands + if (HDA_ICS_IS_BUSY(status)) + { + DebugLog("ExecutePIO timed out waiting for ICS readiness.\n"); + return -1; + } + + //DEBUG_LOG("IntelHDA::ExecutePIO ICB bit clear.\n"); + + // Queue the verb for the HDA controller + mRegMap->ICW = command; + + status = 0x1; // Busy status + mRegMap->ICS = status; + + //DEBUG_LOG("IntelHDA::ExecutePIO Wrote verb and set ICB bit.\n"); + + // Wait for HDA controller to return with a response + for (int i = 0; i < 1000; i++) + { + status = mRegMap->ICS; + + if (!HDA_ICS_IS_BUSY(status)) + break; + + ::IODelay(100); + } + + // Store the result validity while IRV is cleared + bool validResult = HDA_ICS_IS_VALID(status); + + UInt32 response = 0xdeadbeef; //Obvious indication that something weird occurred + + if (validResult) + response = mRegMap->IRR; + + // Reset IRV + status = 0x02; // Valid, Non-busy status + mRegMap->ICS = status; + + if (!validResult) + { + DebugLog("ExecutePIO Invalid result received.\n"); + return -1; + } + + return response; +} diff --git a/VerbStub_Source/VerbStub/IntelHDA.h b/VerbStub_Source/VerbStub/IntelHDA.h new file mode 100644 index 0000000..947e90c --- /dev/null +++ b/VerbStub_Source/VerbStub/IntelHDA.h @@ -0,0 +1,318 @@ +/* + * Released under "The GNU General Public License (GPL-2.0)" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +// +// Adapted from CodecCommander: +// https://github.com/Dolnor/EAPD-Codec-Commander +// + +#ifndef CodecCommander_IntelHDA_h +#define CodecCommander_IntelHDA_h + +#include + +#ifdef DEBUG +# define DebugLog(args...) do { IOLog("VerbStub: " args); } while (0) +#else +# define DebugLog(args...) +#endif + +#define AlwaysLog(args...) do { IOLog("VerbStub: " args); } while (0) + +#define kCodecProfile "Codec Profile" +#define kCodecVendorID "IOHDACodecVendorID" +#define kCodecAddress "IOHDACodecAddress" +#define kCodecRevisionID "IOHDACodecRevisionID" +#define kCodecFuncGroupType "IOHDACodecFunctionGroupType" +#define kCodecSubsystemID "IOHDACodecFunctionSubsystemID" + +// Intel HDA Verbs +#define HDA_VERB_GET_PARAM (UInt16)0xF00 // Get Parameter +#define HDA_VERB_SET_PSTATE (UInt16)0x705 // Set Power State +#define HDA_VERB_GET_PSTATE (UInt16)0xF05 // Get Power State +#define HDA_VERB_EAPDBTL_GET (UInt16)0xF0C // EAPD/BTL Enable Get +#define HDA_VERB_EAPDBTL_SET (UInt16)0x70C // EAPD/BTL Enable Set +#define HDA_VERB_RESET (UInt16)0x7FF // Function Reset Execute +#define HDA_VERB_GET_SUBSYSTEM_ID (UInt16)0xF20 // Get codec subsystem ID + +#define HDA_VERB_SET_AMP_GAIN (UInt8)0x3 // Set Amp Gain / Mute +#define HDA_VERB_GET_AMP_GAIN (Uint8)0xB // Get Amp Gain / Mute + +#define HDA_PARM_NULL (UInt8)0x00 // Empty or NULL payload + +#define HDA_PARM_VENDOR (UInt8)0x00 // Vendor ID +#define HDA_PARM_REVISION (UInt8)0x02 // Revision ID +#define HDA_PARM_NODECOUNT (UInt8)0x04 // Subordinate Node Count +#define HDA_PARM_FUNCGRP (UInt8)0x05 // Function Group Type +#define HDA_PARM_PINCAP (UInt8)0x0C // Pin Capabilities +#define HDA_PARM_PWRSTS (UInt8)0x0F // Supported Power States + +#define HDA_PARM_PS_D0 (UInt8)0x00 // Powerstate D0: Fully on +#define HDA_PARM_PS_D1 (UInt8)0x01 // Powerstate D1 +#define HDA_PARM_PS_D2 (UInt8)0x02 // Powerstate D2 +#define HDA_PARM_PS_D3_HOT (UInt8)0x03 // Powerstate D3Hot +#define HDA_PARM_PS_D3_COLD (UInt8)0x04 // Powerstate D3Cold + +#define HDA_TYPE_AFG 1 // return from PARM_FUNCGRP is 1 for Audio + +// Dynamic payload parameters +#define HDA_PARM_AMP_GAIN_GET(Index, Left, Output) \ + (UInt16)((Output & 0x1) << 15 | (Left & 0x01) << 13 | Index & 0xF) // Get Amp gain / mute + +#define HDA_PARM_AMP_GAIN_SET(Gain, Mute, Index, SetRight, SetLeft, SetInput, SetOutput) \ + (UInt16)((SetOutput & 0x01) << 15 | (SetInput & 0x01) << 14 | (SetLeft & 0x01) << 13 | (SetRight & 0x01) << 12 | \ + (Index & 0xF) << 8 | (Mute & 0x1) << 7 | Gain & 0x7F) // Set Amp gain / mute + +// Determine Immediate Command Busy (ICB) of Immediate Command Status (ICS) +#define HDA_ICS_IS_BUSY(status) ((status) & (1<<0)) + +// Determine Immediate Result Valid (IRV) of Immediate Command Status (ICS) +#define HDA_ICS_IS_VALID(status) ((status) & (1<<1)) + +// Determine if this Pin widget capabilities is marked EAPD capable +#define HDA_PINCAP_IS_EAPD_CAPABLE(capabilities) ((capabilities) & (1<<16)) + +typedef struct __attribute__((packed)) +{ + // 00h: GCAP – Global Capabilities + volatile UInt16 GCAP_OSS : 4; // Number of Output Streams Supported + volatile UInt16 GCAP_ISS : 4; // Number of Input Streams Supported + volatile UInt16 GCAP_BSS : 5; // Number of Bidirectional Streams Supported + volatile UInt16 GCAP_NSDO : 2; // Number of Serial Data Out Signals + volatile UInt16 GCAP_64OK : 1; // 64 Bit Address Supported + // 02h: VMIN – Minor Version + volatile UInt8 VMIN; // Minor Version + // 03h: VMAJ – Major Version + volatile UInt8 VMAJ; // Major Version + // 04h: OUTPAY – Output Payload Capability + volatile UInt16 OUTPAY; // Output Payload Capability + // 06h: INPAY – Input Payload Capability + volatile UInt16 INPAY; // Input Payload Capability + // 08h: GCTL – Global Control + UInt32 : 23; // Reserved + volatile UInt32 GCTL_UNSOL : 1; // Accept Unsolicited Response Enable + UInt32 : 6; // Reserved + volatile UInt32 GCTL_FCNTRL : 1; // Flush Control + volatile UInt32 GCTL_CRST : 1; // Controller Reset + // 0Ch: WAKEEN – Wake Enable + UInt16 : 1; // Reserved + volatile UInt16 WAKEEN_SDIWEN : 15; // SDIN Wake Enable Flags + // 0Eh: STATESTS – State Change Status + UInt16 : 1; // Reserved + volatile UInt16 STATESTS_SDIWAKE: 15; // SDIN State Change Status Flags + // 10h: GSTS – Global Status + UInt16 : 14; // Reserved + volatile UInt16 GSTS_FSTS : 1; // Flush Status + UInt16 : 1; // Reserved + + UInt32 : 32; // Spacer + UInt16 : 16; // Spacer + + // 18h: OUTSTRMPAY – Output Stream Payload Capability + volatile UInt16 OUTSTRMPAY; // Output Stream Payload Capability + // 1Ah: INSTRMPAY – Input Stream Payload Capability + volatile UInt16 INSTRMPAY; // Input Stream Payload Capability + + UInt32 : 32; // Spacer + + // 20h: INTCTL – Interrupt Control + volatile UInt32 INTCTL_GIE : 1; // Global Interrupt Enable + volatile UInt32 INTCTL_CIE : 1; // Controller Interrupt Enable + volatile UInt32 INTCTL_SIE : 30; // Stream Interrupt Enable + // 24h: INTSTS – Interrupt Status + volatile UInt32 INTSTS_GIS : 1; // Global Interrupt Status + volatile UInt32 INTSTS_CIS : 1; // Controller Interrupt Status + volatile UInt32 INTSTS_SIS : 30; // Stream Interrupt Status + + UInt32 : 32; // Spacer + UInt32 : 32; // Spacer + + // 30h: Wall Clock Counter + volatile UInt32 WALL_CLOCK_COUNTER; // Wall Clock Counter + UInt32 : 32; // Spacer + // 38h: SSYNC – Stream Synchronization + UInt32 : 2; // Reserved + volatile UInt32 SSYNC : 30; // Stream Synchronization Bits + + UInt32 : 32; // Spacer + + // 40h: CORB Lower Base Address + volatile UInt32 CORBLBASE; // CORB Lower Base Address + // 44h: CORB Upper Base Address + volatile UInt32 CORBUBASE; // CORB Upper Base Address + // 48h: CORBWP – CORB Write Pointer + UInt16 : 8; // Reserved + volatile UInt16 CORBWP : 8; // CORB Write Pointer + // 4Ah: CORBRP – CORB Read Pointer + volatile UInt16 CORBRPRST : 1; // CORB Read Pointer Reset + UInt16 : 7; // Reserved + volatile UInt16 CORBRP : 8; // CORB Read Pointer + // 4Ch: CORBCTL – CORB Control + UInt8 : 6; // Reserved + volatile UInt8 CORBRUN : 1; // Enable CORB DMA Engine + volatile UInt8 CMEIE : 1; // CORB Memory Error Interrupt Enable + // 4Dh: CORBSTS – CORB Status + UInt8 : 7; // Reserved + volatile UInt8 CMEI : 1; // CORB Memory Error Indication + // 4Eh: CORBSIZE – CORB Size + volatile UInt8 CORBSZCAP : 4; // CORB Size Capability + UInt8 : 2; // Reserved + volatile UInt8 CORBSIZE : 2; // CORB Size + + UInt8 : 8; // Spacer + + // 50h: RIRBLBASE – RIRB Lower Base Address + volatile UInt32 RIRBLBASE; // RIRB Lower Base Address + // 54h: RIRBUBASE – RIRB Upper Base Address + volatile UInt32 RIRBUBASE; // RIRB Upper Base Address + // 58h: RIRBWP – RIRB Write Pointer + volatile UInt16 RIRBWPRST : 1; // RIRB Write Pointer Reset + UInt16 : 7; // Reserved + volatile UInt16 RIRBWP : 8; // RIRB Write Pointer + // 5Ah: RINTCNT – Response Interrupt Count + UInt16 : 8; + volatile UInt16 RINTCNT : 8; // N Response Interrupt Count + // 5Ch: RIRBCTL – RIRB Control + UInt8 : 5; // Reserved + volatile UInt8 RINTCNT_RIRBOIC : 1; // Response Overrun Interrupt Control + volatile UInt8 RINTCNT_RIRBDMAEN: 1; // RIRB DMA Enable + volatile UInt8 RINTCNT_RINTCTL : 1; // Response Interrupt Control + // 5Dh: RIRBSTS – RIRB Status + UInt8 : 5; // Reserved + volatile UInt8 RIRBSTS_RIRBOIS : 1; // Response Overrun Interrupt Status + UInt8 : 1; // Reserved + volatile UInt8 RIRBSTS_RINTFL : 1; // Response Interrupt + // 5Eh: RIRBSIZE – RIRB Size + volatile UInt8 RIRBSIZE_RIRBSZCAP: 4; // RIRB Size Capability + UInt8 : 2; // Reserved + volatile UInt8 RIRBSIZE : 2; // RIRB Size + + UInt8 : 8; // Spacer + + // 60h: Immediate Command Output Interface + volatile UInt32 ICW; // Immediate Command Write + // 64h: Immediate Response Input Interface + volatile UInt32 IRR; // Immediate Response Read + // 68h: Immediate Command Status + union + { + volatile UInt16 ICS; // Immediate Command Status + UInt16 : 8; // Reserved + volatile UInt16 ICS_IRRADD : 4; // Immediate Response Result Address + volatile UInt16 ICS_IRRUNSOL : 1; // Immediate Response Result Unsolicited + volatile UInt16 ICS_ICV : 1; // Immediate Command Version + volatile UInt16 ICS_IRV : 1; // Immediate Result Valid + volatile UInt16 ICS_ICB : 1; // Immediate Command Busy + }; + + UInt32 : 32; // Spacer + UInt16 : 16; // Spacer + + // 70h: DPLBASE – DMA Position Lower Base Address + volatile UInt32 DPLBASE_ADDR : 25; // DMA Position Lower Base Address + UInt32 : 6; + volatile UInt32 DPLBASE_ENBL : 1; // DMA Position Buffer Enable + // 74h: DPUBASE – DMA Position Upper Base Address + volatile UInt32 DPUBASE; // DMA Position Upper Base Address +} HDA_REG, *pHDA_REG; + +// Global Capabilities response +struct HDA_GCAP +{ + UInt16 NumOutputStreamsSupported : 4; + UInt16 NumInputStreamsSupported : 4; + UInt16 NumBidirectionalStreamsSupported : 5; + UInt16 NumSerialDataOutSignals : 2; + UInt16 Supports64bits : 1; +}; + +// Global Capabilities & HDA Version response +struct HDA_GCAP_EXT : HDA_GCAP +{ + UInt8 MinorVersion; + UInt8 MajorVersion; +}; + +enum HDACommandMode +{ + PIO, + DMA +}; + +class IntelHDA +{ + IOPCIDevice* mDevice = NULL; + IODeviceMemory* mDeviceMemory = NULL; + IOMemoryMap* mMemoryMap = NULL; + + pHDA_REG mRegMap = NULL; + + // Initialized in constructor + HDACommandMode mCommandMode; + UInt32 mCodecVendorId; + UInt32 mCodecSubsystemId; + UInt32 mCodecRevisionId; + UInt8 mCodecGroupType; + UInt8 mCodecAddress; + + // Read-once parameters + UInt32 mNodes = -1; + UInt16 mAudioRoot = -1; + +public: + // Constructor + IntelHDA(IOService *provider, HDACommandMode commandMode); + // Destructor + ~IntelHDA(); + + bool initialize(); + + void applyIntelTCSEL(); + + // 12-bit verb and 8-bit payload + UInt32 sendCommand(UInt8 nodeId, UInt16 verb, UInt8 payload); + // 4-bit verb and 16-bit payload + UInt32 sendCommand(UInt8 nodeId, UInt8 verb, UInt16 payload); + + // Send a raw command (verb and payload combined) + UInt32 sendCommand(UInt32 command); + + void resetCodec(); + + UInt32 getCodecVendorId() { return mCodecVendorId; } + UInt8 getCodecAddress() { return mCodecAddress; } + UInt8 getCodecGroupType() { return mCodecGroupType; } + UInt32 getCodecSubsystemId() { return mCodecSubsystemId; } + UInt32 getCodecRevisionId() { return mCodecRevisionId; } + + UInt16 getVendorId(); + UInt16 getDeviceId(); + UInt32 getPCISubId(); + UInt32 getSubsystemId(); + UInt32 getRevisionId(); + + UInt8 getTotalNodes(); + UInt8 getStartingNode(); + +private: + UInt32 executePIO(UInt32 command); + UInt16 getAudioRoot(); +}; + +#endif diff --git a/VerbStub_Source/VerbStub/VerbStub.cpp b/VerbStub_Source/VerbStub/VerbStub.cpp new file mode 100644 index 0000000..3422ab8 --- /dev/null +++ b/VerbStub_Source/VerbStub/VerbStub.cpp @@ -0,0 +1,315 @@ +/* + * Released under "The GNU General Public License (GPL-2.0)" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +// +// Adapted from CodecCommander: +// https://github.com/Dolnor/EAPD-Codec-Commander +// +// Apple Driver Documentation +// +// Writing a kernel extension: +// https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptIOKit/iokit_tutorial.html +// IOKit Fundamentals: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html +// Writing an IOKit driver: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/WritingDeviceDriver/Introduction/Intro.html +// Accessing Hardware: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Intro/AH_Intro.html +// User Client Info (sample user client driver interface): +// https://developer.apple.com/library/content/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html +// + +#include +#include "VerbStub.hpp" + +//********************************************************************* +// VerbStub Main Kernel Driver: +//********************************************************************* + +// This required macro defines the class's constructors, destructors, +// and several other methods I/O Kit requires. +OSDefineMetaClassAndStructors(com_XPS_VerbStub, IOService) + +// Define the driver's superclass. +#define super IOService + +// +// IOKit driver init override (for logging) +// + +bool com_XPS_VerbStub::init(OSDictionary *dict) +{ + bool result = super::init(dict); + IOLog("Initializing...\n"); + return result; +} + +// +// IOkit driver free override (for logging) +// + +void com_XPS_VerbStub::free(void) +{ + IOLog("Freeing...\n"); + super::free(); +} + +// +// IOkit driver probe override (for logging) +// + +IOService *com_XPS_VerbStub::probe(IOService *provider, + SInt32 *score) +{ + IOService *result = super::probe(provider, score); + IOLog("Probing...\n"); + return result; +} + +// This function only gets used by 'start' to set IORegistry properties +static void setNumberProperty(IOService* service, const char* key, UInt32 value) +{ + OSNumber* num = OSNumber::withNumber(value, 32); + if (num) + { + service->setProperty(key, num); + num->release(); + } +} + +// +// IOkit driver start override +// + +bool com_XPS_VerbStub::start(IOService *provider) +{ + bool result = super::start(provider); + IOLog("Starting...\n"); + if (!result) + { + IOLog("Error starting driver.\n"); + return result; + } + + // cache the provider + AudioDevc = provider; + + HDADevice = new IntelHDA(provider, PIO); + if (!HDADevice || !HDADevice->initialize()) + { + IOLog("Error initializing HDADevice instance.\n"); + stop(provider); + return false; + } + + // Populate HDA properties in IORegistry + setNumberProperty(this, kCodecVendorID, HDADevice->getCodecVendorId()); + setNumberProperty(this, kCodecAddress, HDADevice->getCodecAddress()); + setNumberProperty(this, kCodecFuncGroupType, HDADevice->getCodecGroupType()); + setNumberProperty(this, kCodecSubsystemID, HDADevice->getCodecSubsystemId()); + setNumberProperty(this, kCodecRevisionID, HDADevice->getCodecRevisionId()); + + this->registerService(0); + return result; +} + +// +// IOkit driver stop override +// + +void com_XPS_VerbStub::stop(IOService *provider) +{ + IOLog("Stopping...\n"); + + // Free HDADevice + delete HDADevice; + HDADevice = NULL; + + AudioDevc = NULL; + + super::stop(provider); +} + +// +// Execute external command from user client +// + +UInt32 com_XPS_VerbStub::ExternalCommand(UInt32 command) +{ + if (HDADevice) + { + UInt32 response; + response = HDADevice->sendCommand(command); + return response; + } + return -1; +} + +//********************************************************************* +// VerbStub Userspace Client: +//********************************************************************* + +// +// This should match IOConnectCallScalarMethod in hda-verb.c because this +// is the link to user-space. +// + +const IOExternalMethodDispatch VerbStubUserClient::sMethods[kClientNumMethods] = +{ + { // kClientExecuteVerb + (IOExternalMethodAction)&VerbStubUserClient::executeVerb, + 1, // One scalar input value + 0, // No struct inputs + 1, // One scalar output value + 0 // No struct outputs + } +}; + +// Structure of IOExternalMethodDispatch: +// https://developer.apple.com/library/content/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html +/* + struct IOExternalMethodDispatch + { + IOExternalMethodAction function; + uint32_t checkScalarInputCount; + uint32_t checkStructureInputSize; + uint32_t checkScalarOutputCount; + uint32_t checkStructureOutputSize; + }; +*/ + +/* + * Define the metaclass information that is used for runtime + * typechecking of IOKit objects. We're a subclass of IOUserClient. + */ + +OSDefineMetaClassAndStructors(VerbStubUserClient, IOUserClient) + +// +// IOUserClient user-kernel boundary interface init (initWithTask) +// + +bool VerbStubUserClient::initWithTask(task_t owningTask, void* securityID, UInt32 type, OSDictionary* properties) +{ + IOLog("Client::initWithTask(type %u)\n", (unsigned int)type); + + mTask = owningTask; + + return IOUserClient::initWithTask(owningTask, securityID, type, properties); +} + +// +// IOUserClient user-kernel boundary interface start +// + +bool VerbStubUserClient::start(IOService * provider) +{ + bool result = IOUserClient::start(provider); + IOLog("Client::start\n"); + + if(!result) + return(result); + + /* + * Provider is always com_XPS_VerbStub + */ + assert(OSDynamicCast(com_XPS_VerbStub, provider)); + providertarget = (com_XPS_VerbStub*) provider; + + mOpenCount = 1; + + return result; +} + +// +// IOUserClient user-kernel boundary interface client exit behavior +// + +IOReturn VerbStubUserClient::clientClose(void) +{ + if (!isInactive()) + terminate(); + + return kIOReturnSuccess; +} + +// +// IOUserClient user-kernel boundary interface stop override +// + +void VerbStubUserClient::stop(IOService * provider) +{ + IOLog("Client::stop\n"); + + IOUserClient::stop(provider); +} + +// +// IOUserClient handle external method +// + +IOReturn VerbStubUserClient::externalMethod(uint32_t selector, IOExternalMethodArguments* arguments, + IOExternalMethodDispatch* dispatch, OSObject* target, void* reference) +{ + DebugLog("%s[%p]::%s(%d, %p, %p, %p, %p)\n", getName(), this, __FUNCTION__, selector, arguments, dispatch, target, reference); + + if (selector < (uint32_t)kClientNumMethods) + { + dispatch = (IOExternalMethodDispatch *)&sMethods[selector]; + + if (!target) + { + if (selector == kClientExecuteVerb) + target = providertarget; + else + target = this; + } + } + + return IOUserClient::externalMethod(selector, arguments, dispatch, target, reference); +} + +IOReturn VerbStubUserClient::executeVerb(com_XPS_VerbStub* target, void* reference, IOExternalMethodArguments* arguments) +{ + arguments->scalarOutput[0] = target->ExternalCommand((UInt32)arguments->scalarInput[0]); + return kIOReturnSuccess; +} + +//********************************************************************* +// VerbStub Boot-Time Residency Component: +//********************************************************************* + +// +// Stay resident to load the kext when needed +// + +OSDefineMetaClassAndStructors(VerbStubResidency, IOService) + +bool VerbStubResidency::start(IOService *provider) +{ + // announce version + extern kmod_info_t kmod_info; + + // place version in ioreg properties + char buf[128]; + snprintf(buf, sizeof(buf), "%s %s", kmod_info.name, kmod_info.version); + setProperty("VerbStub,Version", buf); + + return super::start(provider); +} diff --git a/VerbStub_Source/VerbStub/VerbStub.hpp b/VerbStub_Source/VerbStub/VerbStub.hpp new file mode 100644 index 0000000..aa6eab5 --- /dev/null +++ b/VerbStub_Source/VerbStub/VerbStub.hpp @@ -0,0 +1,115 @@ +/* + * Released under "The GNU General Public License (GPL-2.0)" + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +// +// Adapted from CodecCommander: +// https://github.com/Dolnor/EAPD-Codec-Commander +// +// Apple Driver Documentation +// +// Writing a kernel extension: +// https://developer.apple.com/library/content/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptIOKit/iokit_tutorial.html +// IOKit Fundamentals: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html +// Writing an IOKit driver: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/WritingDeviceDriver/Introduction/Intro.html +// Accessing Hardware: +// https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Intro/AH_Intro.html +// User Client Info (sample user client driver interface): +// https://developer.apple.com/library/content/samplecode/SimpleUserClient/Listings/User_Client_Info_txt.html +// + +#include +#include +#include "IntelHDA.h" + +// External client methods +enum +{ + kClientExecuteVerb = 0, + kClientNumMethods +}; + +class com_XPS_VerbStub : public IOService +{ + OSDeclareDefaultStructors(com_XPS_VerbStub) +public: + virtual bool init(OSDictionary *dictionary = 0); + virtual void free(void); + virtual IOService *probe(IOService *provider, SInt32 *score); + virtual bool start(IOService *provider); + virtual void stop(IOService *provider); + + UInt32 ExternalCommand(UInt32 command); + +private: // Only for use by com_XPS_VerbStub::functions + IOService *AudioDevc = NULL; + IntelHDA *HDADevice = NULL; + +}; + +class VerbStubUserClient : public IOUserClient +{ + /* + * Declare the metaclass information that is used for runtime + * typechecking of IOKit objects. + */ + + OSDeclareDefaultStructors(VerbStubUserClient) + +private: + com_XPS_VerbStub* providertarget; + task_t mTask; + SInt32 mOpenCount; + + static const IOExternalMethodDispatch sMethods[kClientNumMethods]; + +public: + + /* IOService overrides */ + + virtual bool start(IOService* provider); + virtual void stop(IOService* provider); + + /* IOUserClient overrides */ + + virtual bool initWithTask(task_t owningTask, void * securityID, UInt32 type, OSDictionary* properties); + virtual IOReturn clientClose(void); + + virtual IOReturn externalMethod(uint32_t selector, IOExternalMethodArguments *arguments, IOExternalMethodDispatch* dispatch = 0, + OSObject* target = 0, void* reference = 0); + /* External methods */ + + static IOReturn executeVerb(com_XPS_VerbStub* target, void* reference, IOExternalMethodArguments* arguments); +}; + +class VerbStubResidency : public IOService +{ +private: + + /* + * Declare the metaclass information that is used for runtime + * typechecking of IOKit objects. + */ + + OSDeclareDefaultStructors(VerbStubResidency); + + // standard IOKit methods + virtual bool start(IOService *provider); +}; diff --git a/VerbStub_Source/hda-verb/hda-verb.c b/VerbStub_Source/hda-verb/hda-verb.c new file mode 100644 index 0000000..3590bd6 --- /dev/null +++ b/VerbStub_Source/hda-verb/hda-verb.c @@ -0,0 +1,470 @@ +/* + * Accessing HD-audio verbs via hwdep interface + * Version 0.3 + * + * Copyright (c) 2008 Takashi Iwai + * + * Licensed under GPL v2 or later. + */ + +// +// Adapted from hda-verb from alsa-tools: +// https://www.alsa-project.org/main/index.php/Main_Page +// + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +#include "hda_hwdep.h" + +#define AC_VERB_GET_STREAM_FORMAT 0x0a00 +#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00 +#define AC_VERB_GET_PROC_COEF 0x0c00 +#define AC_VERB_GET_COEF_INDEX 0x0d00 +#define AC_VERB_PARAMETERS 0x0f00 +#define AC_VERB_GET_CONNECT_SEL 0x0f01 +#define AC_VERB_GET_CONNECT_LIST 0x0f02 +#define AC_VERB_GET_PROC_STATE 0x0f03 +#define AC_VERB_GET_SDI_SELECT 0x0f04 +#define AC_VERB_GET_POWER_STATE 0x0f05 +#define AC_VERB_GET_CONV 0x0f06 +#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07 +#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08 +#define AC_VERB_GET_PIN_SENSE 0x0f09 +#define AC_VERB_GET_BEEP_CONTROL 0x0f0a +#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c +#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d +#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e +#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f +#define AC_VERB_GET_GPIO_DATA 0x0f15 +#define AC_VERB_GET_GPIO_MASK 0x0f16 +#define AC_VERB_GET_GPIO_DIRECTION 0x0f17 +#define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18 +#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 +#define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a +#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c +#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 + +#define AC_VERB_SET_STREAM_FORMAT 0x200 +#define AC_VERB_SET_AMP_GAIN_MUTE 0x300 +#define AC_VERB_SET_PROC_COEF 0x400 +#define AC_VERB_SET_COEF_INDEX 0x500 +#define AC_VERB_SET_CONNECT_SEL 0x701 +#define AC_VERB_SET_PROC_STATE 0x703 +#define AC_VERB_SET_SDI_SELECT 0x704 +#define AC_VERB_SET_POWER_STATE 0x705 +#define AC_VERB_SET_CHANNEL_STREAMID 0x706 +#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707 +#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708 +#define AC_VERB_SET_PIN_SENSE 0x709 +#define AC_VERB_SET_BEEP_CONTROL 0x70a +#define AC_VERB_SET_EAPD_BTLENABLE 0x70c +#define AC_VERB_SET_DIGI_CONVERT_1 0x70d +#define AC_VERB_SET_DIGI_CONVERT_2 0x70e +#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f +#define AC_VERB_SET_GPIO_DATA 0x715 +#define AC_VERB_SET_GPIO_MASK 0x716 +#define AC_VERB_SET_GPIO_DIRECTION 0x717 +#define AC_VERB_SET_GPIO_WAKE_MASK 0x718 +#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 +#define AC_VERB_SET_GPIO_STICKY_MASK 0x71a +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e +#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f +#define AC_VERB_SET_CODEC_RESET 0x7ff + +#define AC_PAR_VENDOR_ID 0x00 +#define AC_PAR_SUBSYSTEM_ID 0x01 +#define AC_PAR_REV_ID 0x02 +#define AC_PAR_NODE_COUNT 0x04 +#define AC_PAR_FUNCTION_TYPE 0x05 +#define AC_PAR_AUDIO_FG_CAP 0x08 +#define AC_PAR_AUDIO_WIDGET_CAP 0x09 +#define AC_PAR_PCM 0x0a +#define AC_PAR_STREAM 0x0b +#define AC_PAR_PIN_CAP 0x0c +#define AC_PAR_AMP_IN_CAP 0x0d +#define AC_PAR_CONNLIST_LEN 0x0e +#define AC_PAR_POWER_STATE 0x0f +#define AC_PAR_PROC_CAP 0x10 +#define AC_PAR_GPIO_CAP 0x11 +#define AC_PAR_AMP_OUT_CAP 0x12 +#define AC_PAR_VOL_KNB_CAP 0x13 + +/* + */ +#define VERBSTR(x) { .val = AC_VERB_##x, .str = #x } +#define PARMSTR(x) { .val = AC_PAR_##x, .str = #x } + +struct strtbl { + int val; + const char *str; +}; + +static struct strtbl hda_verbs[] = { + VERBSTR(GET_STREAM_FORMAT), + VERBSTR(GET_AMP_GAIN_MUTE), + VERBSTR(GET_PROC_COEF), + VERBSTR(GET_COEF_INDEX), + VERBSTR(PARAMETERS), + VERBSTR(GET_CONNECT_SEL), + VERBSTR(GET_CONNECT_LIST), + VERBSTR(GET_PROC_STATE), + VERBSTR(GET_SDI_SELECT), + VERBSTR(GET_POWER_STATE), + VERBSTR(GET_CONV), + VERBSTR(GET_PIN_WIDGET_CONTROL), + VERBSTR(GET_UNSOLICITED_RESPONSE), + VERBSTR(GET_PIN_SENSE), + VERBSTR(GET_BEEP_CONTROL), + VERBSTR(GET_EAPD_BTLENABLE), + VERBSTR(GET_DIGI_CONVERT_1), + VERBSTR(GET_DIGI_CONVERT_2), + VERBSTR(GET_VOLUME_KNOB_CONTROL), + VERBSTR(GET_GPIO_DATA), + VERBSTR(GET_GPIO_MASK), + VERBSTR(GET_GPIO_DIRECTION), + VERBSTR(GET_GPIO_WAKE_MASK), + VERBSTR(GET_GPIO_UNSOLICITED_RSP_MASK), + VERBSTR(GET_GPIO_STICKY_MASK), + VERBSTR(GET_CONFIG_DEFAULT), + VERBSTR(GET_SUBSYSTEM_ID), + + VERBSTR(SET_STREAM_FORMAT), + VERBSTR(SET_AMP_GAIN_MUTE), + VERBSTR(SET_PROC_COEF), + VERBSTR(SET_COEF_INDEX), + VERBSTR(SET_CONNECT_SEL), + VERBSTR(SET_PROC_STATE), + VERBSTR(SET_SDI_SELECT), + VERBSTR(SET_POWER_STATE), + VERBSTR(SET_CHANNEL_STREAMID), + VERBSTR(SET_PIN_WIDGET_CONTROL), + VERBSTR(SET_UNSOLICITED_ENABLE), + VERBSTR(SET_PIN_SENSE), + VERBSTR(SET_BEEP_CONTROL), + VERBSTR(SET_EAPD_BTLENABLE), + VERBSTR(SET_DIGI_CONVERT_1), + VERBSTR(SET_DIGI_CONVERT_2), + VERBSTR(SET_VOLUME_KNOB_CONTROL), + VERBSTR(SET_GPIO_DATA), + VERBSTR(SET_GPIO_MASK), + VERBSTR(SET_GPIO_DIRECTION), + VERBSTR(SET_GPIO_WAKE_MASK), + VERBSTR(SET_GPIO_UNSOLICITED_RSP_MASK), + VERBSTR(SET_GPIO_STICKY_MASK), + VERBSTR(SET_CONFIG_DEFAULT_BYTES_0), + VERBSTR(SET_CONFIG_DEFAULT_BYTES_1), + VERBSTR(SET_CONFIG_DEFAULT_BYTES_2), + VERBSTR(SET_CONFIG_DEFAULT_BYTES_3), + VERBSTR(SET_CODEC_RESET), + { }, /* end */ +}; + +static struct strtbl hda_params[] = { + PARMSTR(VENDOR_ID), + PARMSTR(SUBSYSTEM_ID), + PARMSTR(REV_ID), + PARMSTR(NODE_COUNT), + PARMSTR(FUNCTION_TYPE), + PARMSTR(AUDIO_FG_CAP), + PARMSTR(AUDIO_WIDGET_CAP), + PARMSTR(PCM), + PARMSTR(STREAM), + PARMSTR(PIN_CAP), + PARMSTR(AMP_IN_CAP), + PARMSTR(CONNLIST_LEN), + PARMSTR(POWER_STATE), + PARMSTR(PROC_CAP), + PARMSTR(GPIO_CAP), + PARMSTR(AMP_OUT_CAP), + PARMSTR(VOL_KNB_CAP), + { }, /* end */ +}; + +// +// Global Variables +// + +io_service_t VerbStubIOService; +io_connect_t DataConnection; +uint32_t connectiontype = 0; + +// +// Open connection to IOService +// + +uint32_t OpenServiceConnection() +{ + // + // Having a kernel-side server (VerbStub) and a user-side client (hda-verb) is really the only way to ensure that hda- + // verb won't break when IOAudioFamily changes. This 2-component solution is necessary because we can't compile kernel + // libraries into user-space programs on macOS and expect them to work generically. + // + // Additionally, if this program were made as a single executable that accessed device memory regions directly, it would + // only be guaranteed to work for one machine on one BIOS version since memory regions change depending on hardware + // configurations. This is why Raspberry Pis, STM32s, and other embedded platforms are nice to program on: They don't + // change much between versions so programs can be made extremely lightweight. Linux also does a pretty good job + // achieving a similar situation, since everything (devices, buses, etc.) on Linux is represented by an easily + // accessible file (just look at how simple the hda-verb program in alsa-tools is! All it uses is ioctl). + // + + CFMutableDictionaryRef dict = IOServiceMatching("com_XPS_VerbStub"); + + // Use IOServiceGetMatchingService since we can reasonably expect "VerbStub" is the only IORegistryEntry of its kind. + // Otherwise IOServiceGetMatchingServices with an iterating algorithm must be used to find the kernel extension. + + VerbStubIOService = IOServiceGetMatchingService(kIOMasterPortDefault, dict); + + // Hopefully the kernel extension loaded properly so it can be found. + + if (!VerbStubIOService) + { + fprintf(stderr, "Could not locate VerbStub kext. Ensure it is loaded; verbs cannot be sent otherwise.\n"); + return -1; + } + + // Connect to the IOService object + // Note: kern_return_t is just an int + kern_return_t kernel_return_status = IOServiceOpen(VerbStubIOService, mach_task_self(), connectiontype, &DataConnection); + + if (kernel_return_status != kIOReturnSuccess) + { + fprintf(stderr, "Failed to open VerbStub IOService: %08x.\n", kernel_return_status); + return -1; + } + + return kernel_return_status; // 0 if successful +} + +// +// Send verb command +// + +static uint32_t VerbCommand(uint32_t command) +{ + // + // Call the function ultimately responsible for sending commands in the kernel extension. That function will return the + // response we also want. + // https://lists.apple.com/archives/darwin-drivers/2008/Mar/msg00007.html + // + + uint32_t inputCount = 1; // Number of input arguments + uint32_t outputCount = 1; // Number of elements in output + uint64_t input = command; // Array of input scalars + uint64_t output; // Array of output scalars + + // IOConnectCallScalarMethod was introduced in Mac OS X 10.5 + + kern_return_t kernel_return_status = IOConnectCallScalarMethod(DataConnection, connectiontype, &input, inputCount, &output, &outputCount); + + if (kernel_return_status != kIOReturnSuccess) + { + fprintf(stderr, "Error sending command.\n"); + return -1; + } + + // Return command response + return (uint32_t)output; +} + +// +// Close connection to IOService +// + +void CloseServiceConnection() +{ + // Done with the VerbStub IOService object, so we don't need to hold on to it anymore + IOObjectRelease(VerbStubIOService); +} + +static void list_keys(struct strtbl *tbl, int one_per_line) +{ + int c = 0; + for (; tbl->str; tbl++) { + size_t len = strlen(tbl->str) + 2; + if (!one_per_line && c + len >= 80) { + fprintf(stderr, "\n"); + c = 0; + } + if (one_per_line) + fprintf(stderr, " %s\n", tbl->str); + else if (!c) + fprintf(stderr, " %s", tbl->str); + else + fprintf(stderr, ", %s", tbl->str); + c += 2 + len; + } + if (!one_per_line) + fprintf(stderr, "\n"); +} + +/* look up a value from the given string table */ +static int lookup_str(struct strtbl *tbl, const char *str) +{ + struct strtbl *p, *found; + size_t len = strlen(str); + + found = NULL; + for (p = tbl; p->str; p++) { + if (!strncmp(str, p->str, len)) { + if (found) { + fprintf(stderr, "No unique key '%s'\n", str); + return -1; + } + found = p; + } + } + if (!found) { + fprintf(stderr, "No key matching with '%s'\n", str); + return -1; + } + return found->val; +} + +/* convert a string to upper letters */ +static void strtoupper(char *str) +{ + for (; *str; str++) + *str = toupper(*str); +} + +static void usage(void) +{ + fprintf(stderr, "usage: hda-verb [option] nid verb param\n"); + fprintf(stderr, " -l List known verbs and parameters\n"); + fprintf(stderr, " -L List known verbs and parameters (one per line)\n"); +} + +static void list_verbs(int one_per_line) +{ + fprintf(stderr, "known verbs:\n"); + list_keys(hda_verbs, one_per_line); + fprintf(stderr, "known parameters:\n"); + list_keys(hda_params, one_per_line); +} + +// +// Main +// + +int main(int argc, char **argv) +{ + // Local variables + kern_return_t ServiceConnectionStatus; + int version, c, timeout; + int nid, verb, param; + struct hda_verb_ioctl val; + char **p; + int trylimit = 5; + + // Check for -l or -L flag + while ((c = getopt(argc, argv, "lL")) >= 0) { + switch (c) { + case 'l': + list_verbs(0); + return 0; + case 'L': + list_verbs(1); + return 0; + default: + usage(); + return 1; + } + } + + // Check for correct number of command-line arguments + if (argc - optind < 3) { + usage(); + return 1; + } + + // Mac version of hda-verb + version = 0x2710; // Darwin + + // If this error appears, the program was compiled incorrectly + if (version < HDA_HWDEP_VERSION) { + fprintf(stderr, "Invalid version number 0x%x\n", version); + return 1; + } + + p = argv + optind; + nid = strtol(*p, NULL, 0); // Don't worry about the warning here. This should never be bigger than an int. + if (nid < 0 || nid > 0xff) { + fprintf(stderr, "invalid nid %s\n", *p); + return 1; + } + + p++; + if (!isdigit(**p)) { + strtoupper(*p); + verb = lookup_str(hda_verbs, *p); + if (verb < 0) + return 1; + } else { + verb = strtol(*p, NULL, 0); // Don't worry about the warning here. This should never be bigger than an int. + if (verb < 0 || verb > 0xfff) { + fprintf(stderr, "invalid verb %s\n", *p); + return 1; + } + } + p++; + if (!isdigit(**p)) { + strtoupper(*p); + param = lookup_str(hda_params, *p); + if (param < 0) + return 1; + } else { + param = strtol(*p, NULL, 0); // Don't worry about the warning here. This should never be bigger than an int. + if (param < 0 || param > 0xffff) { + fprintf(stderr, "invalid param %s\n", *p); + return 1; + } + } + // Establish user-kernel connection + timeout = 0; + ServiceConnectionStatus = OpenServiceConnection(); + if (ServiceConnectionStatus != kIOReturnSuccess) + { + while (ServiceConnectionStatus != kIOReturnSuccess && timeout < trylimit) + { + timeout++; + fprintf(stderr, "Error establshing IOService connection. Retrying in 1 second... (Attempt #%d/%d)\n", timeout, trylimit); + sleep (1); + ServiceConnectionStatus = OpenServiceConnection(); + } + } + + if (timeout == trylimit) + { + return kIOReturnError; + } + + // Parameter display indicates successful connection + fprintf(stderr, "nid = 0x%x, verb = 0x%x, param = 0x%x\n", + nid, verb, param); + + // Properly format command + val.verb = HDA_VERB(nid, verb, param); + fprintf(stderr, "Verb Command = 0x%x\n", val.verb); + + // Send command + val.res = VerbCommand(val.verb); + fprintf(stderr, "Response = 0x%x\n", val.res); + + // Clean up and exit + CloseServiceConnection(); + return 0; +} diff --git a/VerbStub_Source/hda-verb/hda_hwdep.h b/VerbStub_Source/hda-verb/hda_hwdep.h new file mode 100644 index 0000000..bb753f3 --- /dev/null +++ b/VerbStub_Source/hda-verb/hda_hwdep.h @@ -0,0 +1,42 @@ +/* + * HWDEP Interface for HD-audio codec + * + * Copyright (c) 2007 Takashi Iwai + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Adapted from hda-verb from alsa-tools: +// https://www.alsa-project.org/main/index.php/Main_Page +// + +#ifndef __SOUND_HDA_HWDEP_H +#define __SOUND_HDA_HWDEP_H + +#define HDA_HWDEP_VERSION 0x2710 /* Darwin */ + +/* verb */ +#define HDA_REG_NID_SHIFT 20 +#define HDA_REG_VERB_SHIFT 8 +#define HDA_REG_VAL_SHIFT 0 +#define HDA_VERB(nid,verb,param) ((nid)<<20 | (verb)<<8 | (param)) + +struct hda_verb_ioctl { + u32 verb; /* HDA_VERB() */ + u32 res; /* response */ +}; + +#endif