I decided to make a communication pipes implementation as library so that it can be used with other USB hardware. The library uses two bulk endpoints and control endpoint. One bulk endpoint is for receiving the data and the other for sending the data. The default control endpoint (EP0) is used for communication control.
User's code should repeatedly call single function in library which does nothing while no data is received and calls user's function when new packet arrives.
Larger communication buffers are better for faster communication. To improve it even more the USB implementation should use double buffered endpoints - not the case at the moment.