Some comments from experience with Cakewalk ACT. NOT as a proposal to do the same. I will go my own way, as I have done with ACT, probably again alone. But that has helped many people and so I am going to continue at my "new home" (that is not related to this thread).
General problematic for Control Surfaces and why "MIDI Learn", implemented in all DAWS, in not perfect: the number of physical controls in N, the number of controllable parameters is M. M is 10-1000 bigger then N, even in a simple project. Some surfaces support several layouts in firmware, effectively making N*2 ... N*5 distinguishable controls from the DAW perspective. For controlling fixed subset of parameters, f.e. for live performance, that is sufficient. But from general project perspective, that is a drop of water into the ocean (and has side effects for knobs and sliders, so works well for buttons and encoders only).
In a project without plug-ins, so for bare DAW recording/mixing, the set of parameters is always the same: O(10) per track (Volume, mute, etc.), O(10) for transport (play, loop, etc.), plus O(10) actions (ala toolbox). Since the only variable component is the track number, making the Surface control one track (f.e. Faderport) or a group of tracks (MCU) and providing a way to switch the track/group takes the number of parameter under control. The result can be "hard-coded" then, as done in binary plug-ins for particular surfaces in all DAWs.
With plug-ins the situation is worse. Many of them have O(1000) parameters and the number of plug-ins in power user collection is also O(1000). So unlike with controlling DAW, where O(10) physical controls should be mapped to O(100) parameters, we have O(10) to O(1000000) mapping problem.
I have observed several approaches:
1) fix plug-ins as a part of the DAW (as fixed "channel strips"), f.e. EQ/Comp in old Sonar, MixBus. Than controller can take the approach used for the DAW, with (semi)hardcoded mapping.
2) "prepare" plug-ins for outside controlling by internal mapping (preset dependent) to some reasonable number of extra exposed controls (like 8 knobs + some buttons). Most heavy softsynth use that.
3*) organize X banks with Y modifiers, to bring the order of available controls up to the order of parameters and let the user select what they really need. F.e (8 knobs + 8 sliders + 8 buttons) x 4 banks lean toward O(100). Covers most not aggregated FXes completely and allow only factor 10 reduction for power synth.
3 is still not solved perfectly, asking the user to map up to 100000 parameters manually. Here is the ACT attempt to solve that:
a) prepare a generic list of all parameters. Plug-in provide its own order. Unfortunately, most plug-ins have to sorted it by "usability" and so:
b) try to put known by name parameters at the top of the list (f.e. power -> first button, gain -> first knob, etc.). By analyzing representative set of plug-ins, the result of such automatic ordering can be usable. Unfortunately, only primitive searching was implemented in ACT. Categorized searching can have better result (f.e. "detect" the plug-in is EQ and use EQ specific priority list).
c) distribute constructed list to available list of controls. Some surface has 8 knobs, some 3, some 24. ACT put at least some logic in mapping, it takes parameters one by one giving already re-mapped by user parameters the priority, up to "ignoring" proposed control type (so if user has manually mapped 8 knobs and now there are 4 knobs and 4 sliders, 4 knobs are shifted to sliders). While the idea looks nice, in practice, the result is horribly. If user has decided to give one more physical control for plug-ins, the whole mapping can be shifted.
4) finally, user can map everything manually. So the mapping is Per plugin x Per surface.
I was thinking a lot how to improve (b) and (c), but without reasonable proposals so far.
But may be someone else, looking at the problematic, will find a good solution