Skip to content

Commit

Permalink
add a translator from endpoint index to number
Browse files Browse the repository at this point in the history
LibUSB::InterfaceImpl::getEndpoint() throws a logic_error exception
if the index and endpoint number are not equal. This presents a
problem communicating with a USB device, based on the Cypress
CY7C68001 chip which only implements endpoint numbers 2, 4, 6 and 8
in addition to 0.

Libusbpp had incorrectly made a assumption that all USB devices have
linear endpoint numbering. The Libusbpp should be handled the linear
and non linear numbering in same way.

LibUSB::Interface{Impl}::getEndpoint() has been refectored to expect
a number (not a index) explicitly.

LibUSB::Interface{Impl}::getEPNumberByIndex() is a new public method
to translate a given endpoint index to the corresponding endpoint
number. This number can be used together with getEndpoint() to get
the corresponding endpoint object in a fast way.

Example:

    std::shared_ptr<LibUSB::Interface> pInterface = /* ... */
    for (int epidx = 1;
             epidx <= pInterface->NumEndpoints();
             epidx++)
    {
        std::shared_ptr<LibUSB::Endpoint> pEndpoint;
        pEndpoint = pInterface->getEndpoint(
                    pInterface->getEPNumberByIndex(epidx)
            );

        /* ... */
    }

A new use case for getEPNumberByIndex() is the creation of a map of
endpoint numbers by it corresponding index as a key. Walk throught
such a list gives access to all available endpoint numbers
independent of a specific context.

Example:

    typedef std::map<int, int> EndpointNumbers_t;
    EndpointNumbers_t mEndpointNumbers;

    std::shared_ptr<LibUSB::Interface> pInterface = /* ... */
    for (int epidx = 1;
             epidx <= pInterface->NumEndpoints();
             epidx++)
    {

        mEndpointNumbers.insert(
            std::make_pair(
                epidx, pInterface->getEPNumberByIndex( epidx )
            )
        );

    }

    /* ... */

    for (const auto &epnum : mEndpointNumbers)
    {
        std::shared_ptr<LibUSB::Endpoint> pEndpoint;
        pEndpoint =pInterface->getEndpoint(epnum.second);

        /* ... */
    }

Based on this concept the interface class provides the new public
method LibUSB::Interface::getEndpointNumbers() to reduce the effort
for the user.

Example (the same as befor, but just simpler):

    std::shared_ptr<LibUSB::Interface> pInterface = /* ... */

    LibUSB::Interface::EndpointNumbers_t mEndpointNumbers;
    mEndpointNumbers = pInterface->getEndpointNumbers();

    /* ... */

    for (const auto &epnum : mEndpointNumbers)
    {
        std::shared_ptr<LibUSB::Endpoint> pEndpoint;
        pEndpoint =pInterface->getEndpoint(epnum.second);

        /* ... */
    }

Related-to-issue: zarthcode#3
Signed-off-by: Stephan Linz <[email protected]>
  • Loading branch information
rexut committed Nov 28, 2016
1 parent e7bc850 commit a158afe
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 21 deletions.
7 changes: 4 additions & 3 deletions examples/LibusbTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,12 @@ int main(int argc, char* argv[])
std::wcout << L"\t\tInterface descriptor:" << pInterface->DescriptorString() << std::endl;
std::wcout << L"\t\tInterface Number of endpoints: " << std::dec << pInterface->NumEndpoints() << std::endl << std::endl;

// Iterate over the interface endpoints (other than ep0!!)
for (int epnum = 1; epnum <= pInterface->NumEndpoints(); epnum++)
// Iterate over the interface endpoints (other than ep0!!) - by the index to number map
LibUSB::Interface::EndpointNumbers_t mEndpointNumbers = pInterface->getEndpointNumbers();
for (const auto &epnum : mEndpointNumbers)
{

std::shared_ptr<LibUSB::Endpoint> pEndpoint = pInterface->getEndpoint(epnum);
std::shared_ptr<LibUSB::Endpoint> pEndpoint = pInterface->getEndpoint(epnum.second);

/// Endpoint information
std::wcout << L"\t\t\tEndpoint number: " << std::dec << pEndpoint->Number() << std::endl;
Expand Down
14 changes: 12 additions & 2 deletions headers/libusbpp/Interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
#ifndef LIBUSBPP_INTERFACE_HPP
#define LIBUSBPP_INTERFACE_HPP

#include <memory>
#include <string>
#include <memory>
#include <map>

#include <stdint.h>

Expand Down Expand Up @@ -78,8 +79,17 @@ namespace LibUSB
/// Returns the number of endpoints this interface has.
int NumEndpoints()const;

/// Returns the number of a specified endpoint
int getEPNumberByIndex(int index)const;

/// Endpoint number container type (index -> number)
typedef std::map<int, int> EndpointNumbers_t;

/// Returns the number container of all endpoint indices
EndpointNumbers_t getEndpointNumbers()const;

/// Returns the specified endpoint
std::shared_ptr<Endpoint> getEndpoint(int index);
std::shared_ptr<Endpoint> getEndpoint(int number);

protected:
private:
Expand Down
22 changes: 20 additions & 2 deletions src/Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,27 @@ int LibUSB::Interface::NumEndpoints() const
return m_pInterfaceImpl->NumEndpoints();
}

std::shared_ptr<LibUSB::Endpoint> LibUSB::Interface::getEndpoint( int index )
int LibUSB::Interface::getEPNumberByIndex( int index ) const
{
return m_pInterfaceImpl->getEndpoint(index);
return m_pInterfaceImpl->getEPNumberByIndex(index);
}

LibUSB::Interface::EndpointNumbers_t LibUSB::Interface::getEndpointNumbers() const
{
EndpointNumbers_t mEndpointNumbers;

// Create each endpoint number
for (int i = 1; i <= NumEndpoints(); i++)
{
mEndpointNumbers.insert(std::make_pair(i,getEPNumberByIndex(i)));
}

return mEndpointNumbers;
}

std::shared_ptr<LibUSB::Endpoint> LibUSB::Interface::getEndpoint( int number )
{
return m_pInterfaceImpl->getEndpoint(number);
}

bool LibUSB::Interface::isClaimed() const
Expand Down
60 changes: 48 additions & 12 deletions src/InterfaceImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,50 @@ uint8_t LibUSB::InterfaceImpl::NumEndpoints() const
return m_pInterface->altsetting[m_alternateSetting].bNumEndpoints;
}

std::shared_ptr<LibUSB::Endpoint> LibUSB::InterfaceImpl::getEndpoint( uint8_t index )
uint8_t LibUSB::InterfaceImpl::getEPNumberByIndex( uint8_t index ) const
{
if (index == 0)
{
// Return the number zero of the device control endpoint.
return index;
}


if (index > NumEndpoints())
{
throw std::logic_error("LibUSB::InterfaceImpl::getEPNumberByIndex() - index out of range.");
}


// Find the number of endpoint
EndpointContainer_t::const_iterator itEndpoint = m_EndpointContainer.begin();
std::advance(itEndpoint, index - 1);

std::shared_ptr<LibUSB::Endpoint> pEndpoint;
if (itEndpoint != m_EndpointContainer.end())
{

pEndpoint = itEndpoint->second;

/// \note #2 Validate endpoint number.
if (!pEndpoint->Number())
{
throw std::logic_error("LibUSB::InterfaceImpl::getEPNumberByIndex() - endpoint has no number as expected! (note #2)");
}

}
else
{
throw std::logic_error("LibUSB::InterfaceImpl::getEPNumberByIndex() - endpoint not found.");
}


return pEndpoint->Number();
}

std::shared_ptr<LibUSB::Endpoint> LibUSB::InterfaceImpl::getEndpoint( uint8_t number )
{
if (number == 0)
{

// Return the device control endpoint zero.
Expand All @@ -296,26 +337,21 @@ std::shared_ptr<LibUSB::Endpoint> LibUSB::InterfaceImpl::getEndpoint( uint8_t in

}

if (index > m_pInterface->altsetting[m_alternateSetting].bNumEndpoints)
{
throw std::logic_error("LibUSB::InterfaceImpl::getEndpoint() - index out of range.");
}


// Find the endpoint
EndpointContainer_t::iterator itEndpoint = m_EndpointContainer.find(index);
EndpointContainer_t::iterator itEndpoint = m_EndpointContainer.find(number);

std::shared_ptr<LibUSB::Endpoint> pEndpoint;

if (itEndpoint != m_EndpointContainer.end())
{

pEndpoint = m_EndpointContainer.find(index)->second;
pEndpoint = m_EndpointContainer.find(number)->second;

/// \note #1 Validate endpoint number against its index.
if (pEndpoint->Number() != index)
/// \note #1 Validate endpoint number against its number.
if (pEndpoint->Number() != number)
{
throw std::logic_error("LibUSB::InterfaceImpl::getEndpoint() - endpoint and index do not match as expected! (note #1)");
throw std::logic_error("LibUSB::InterfaceImpl::getEndpoint() - endpoint and number do not match as expected! (note #1)");
}

}
Expand Down Expand Up @@ -393,7 +429,7 @@ void LibUSB::InterfaceImpl::CreateEndpoints()
else
{

// I'm not positive that I want to disallow reusing already existing endpoints (ie, claim() the same interface
// I'm not positive that I want to disallow reusing already existing endpoints, i.e.: claim() the same interface

}

Expand Down
7 changes: 5 additions & 2 deletions src/InterfaceImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ namespace LibUSB
/// Returns the number of endpoints this interface/altsetting has.
uint8_t NumEndpoints()const;

/// Returns the number of a specified endpoint
uint8_t getEPNumberByIndex(uint8_t index)const;

/// Returns the specified endpoint
std::shared_ptr<Endpoint> getEndpoint(uint8_t index);
std::shared_ptr<Endpoint> getEndpoint(uint8_t number);

protected:

Expand All @@ -112,7 +115,7 @@ namespace LibUSB
/// Indicates that there has been through a successful Claim()
bool m_bClaimed;

/// Endpoint container type
/// Endpoint container type (number -> enpoint)
typedef std::map<uint8_t, std::shared_ptr<Endpoint>> EndpointContainer_t;

/// Endpoint container
Expand Down

0 comments on commit a158afe

Please sign in to comment.