hardware abstraction layer vs device driver