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