A lot of answers to this question are in the understanding of how ros_control works. Below there are three links that will explain how it does work:
So, to answer your questions, I'll make a briefing that how ros_control works. In ros_control there are a lot of layers as you can see in this image
*Source: * ros_control wiki
Starting from down to up, the Real Robot in your case is the dc motors and its encoders. So, the first thing that you need to do is to write one class to control the velocity of the dc motors and another class to read the values from the encoders. These classes could be totally independent of ROS. My suggestion is to implement methods that get an angular velocity as an argument and convert this value to PWM and for encoders, you need to implement methods to get angular velocity and position for each wheel. Below some examples that I made for my robot
If possible, my suggestion is to make an independent process only to control the wheels. So in this process, you will implement the PID for each wheel. And the communication with this process could be through a UDP socket for example. Another solution is to make the control process in a microcontroller and communicate with it through a serial interface like UART.
After this implementation, you need to implement the RobotHW. Is the RobotHW that get the velocities from diff_drive_controller and send it to the real robot. The RobotHW is a class that has some virtual methods: init, write, and read. You need to inherit this class and implement these virtual methods. The init method is where is some initialization methods like to open the communication port. The write method is where you send the commands to the real robot. The commands are the angular velocity for each wheel. Based in my suggestions above, these commands would be sent through UDP socket or UART interface. Finally, the read is the method that you get the values from the encoders. Remember that for diff_drive_controller you need to provide angular velocity and position. Follow the example for my robot:
Note: In my robot I didn't make an independent process to control the wheel. It Is in the future plan to do this. And how I tried to use the wheels control mixed with the main loop control (I'll talk about it yet) I don't recommend this approach
The yellow block of the diagram is where is the diff_drive_controller. The diff_driver_controller based on the physical parameters of your robot (wheel diameter and distance between wheels), that is passed in a config file like this, compute which is the angular velocity that must be applied in each wheel of the robot to it reaches the linear and angular velocities published in the cmd_vel topic. To compute the odometry data and then makes the ... (more)
The basic answer to your questions is that you are the one to implement it. diff_drive_controller takes at input the velocities from each wheel and generates as output the desired velocity for each wheel. So the wheel velocity<->hardware needs to be done by you in your Implementation of hardware_interface::RobotHW
It is probably a good idea to copy from examples, e.g. this answer
ok, but where does he publish the velocity information for each wheel?