Packet sockets as-is are a great option if that's your use case but if I just want to bind to ethertype 0x88CC I shouldn't need to ask for the same permissions I can use to bind to 0x0800 or to capture all traffic. Sure, that's how things like AF_PACKET are implemented but there is nothing about being lower level that requires this all or nothing game of read/write-full-access-to-all-packets-ignoring-the-rest-of-the-os-stack-state vs bind-a-single-TCP/UDP-port. Just look at the way shared binds and privileged ports are handled for TCP, there is no reason the same concepts couldn't be applied to lower layers for more granularity.
All of that aside, none of this would explain why I need to write a custom network driver in Windows to send more than a couple predefined ethertypes from user space at all or why, in Linux, the network filter layer can't apply to any family used in the sendto() syscall instead of just sendto() calls with AF_INET set. These kinds of decisions aren't rooted in a limited scope of what packet sockets can be for or how they must interact with the rest of the network stack, it's just how they are currently built and exposed. This is great if your use case is to ignore the OS stack, but that doesn't mean doing so is the only conceivable way of packet sockets being built.
If BPF were treated slightly differently in terms of how/when certain abilities were exposed it could be a great answer to all of this. As of right now, it's just a better way to ignore the OS network stack even more than normal though.