This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Control multiple USB bulk devices

Our new system will have multiple TM4C123 MCU and we want to communicate with them through USB bulk device class. Is it possible  or we have to change to another USB device class? 

We have two EX-TM4C123GXL launchpads and can rum usb_dev_bulk sample code with lmusbdll.lib on single evaluation board successfully. but we configure the second  board as

// Set the USB stack mode to Device mode with VBUS monitoring.

USBStackModeSet(1, eUSBModeForceDevice, 0);

// Pass our device information to the USB library and place the device on the bus.
USBDBulkInit(1, &g_sBulkDevice);

and call lmusbdll function

m_hUSB = InitializeDeviceByIndex(BULK_VID, BULK_PID, (LPGUID)&(GUID_DEVINTERFACE_TIVA_BULK), 1, TRUE, &bDriverInstalled);

the returned m_hUSB is always NULL.

Any one can teach me how to communicate two launchpads at the same time by USB? Thanks lot in advance!

Ned

  • Hello Ned,

    We would wish the USB was that simple. First of all the Index is not the Device but it is a reference made by the Host controller (in this case PC). So you need to change the Device code back to what it was. The Host uses the Unique String number as given by the String Index in the device descriptor to access each of the numerated device.

    So the first thing on the host controller side, is to get the Device String which holds the Unique number for all the connected devices. The device that matches the expected index is then opened by specifically calling by index now.

    You may want to look at the dfuprog.cpp in TivaWare/tools/dfuprog to see how it is done for DFU mode.

    Regards
    Amit
  • Hi Amit,

    Thanks lot for your quick response. By your guidance and my understanding, should we need to change device's USB bulk class to USB DFU class, and use lmdfu.dll on top of lmusbdll in PC software side? Thanks!

    Ned

  • Hello Ned,

    No. You would need to use the same logic to access a particular device.

    Regards
    Amit
  • Hi Amit,

    I'm confused. Please point out where I'm doing wrong

    In two devices, we configure both as USB controller 0, but different g_ppui8StringDescriptors in "usb_bulk_structures.c"

    // Set the USB stack mode to Device mode with VBUS monitoring.
    USBStackModeSet(0, eUSBModeForceDevice, 0);

    // Pass our device information to the USB library and place the device on the bus
    USBDBulkInit(0, &g_sBulkDevice);

    One g_pui8ProductString of g_ppui8StringDescriptors is "Product-0" and another is "Product-1".

    In the host PC, we call InitializeDeviceByIndex function of lmusbdll with dwIndex = 0 and dwIndex = 1, but we couldn't get the information of g_ppui8StringDescriptors because lmusbdll does not have such function. Following is the lmusbdll header file

    //*****************************************************************************
    //
    // lmusbdll.h : Main header file for the Tiva USB interface DLL.
    //
    // Copyright (c) 2008-2015 Texas Instruments Incorporated. All rights reserved.
    // Software License Agreement
    //
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    // This is part of revision 2.1.1.71 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************

    #ifdef __cplusplus

    #pragma once

    #ifndef __AFXWIN_H__
    #error "include 'stdafx.h' before including this file for PCH"
    #endif

    //
    // Functions exported by this DLL.
    //
    extern "C" {
    #endif

    //****************************************************************************
    //
    // A handle returned by InitializeDevice().
    //
    //****************************************************************************
    typedef void *LMUSB_HANDLE;

    //****************************************************************************
    //
    // Flags used in constructing the ucRequestType parameter to Endpoint0Transfer().
    //
    //****************************************************************************
    #define REQUEST_TRANSFER_IN 0x80
    #define REQUEST_TRANSFER_OUT 0x00

    #define REQUEST_TYPE_STANDARD 0x00
    #define REQUEST_TYPE_CLASS 0x20
    #define REQUEST_TYPE_VENDOR 0x40

    #define REQUEST_RECIPIENT_DEVICE 0x00
    #define REQUEST_RECIPIENT_INTERFACE 0x01
    #define REQUEST_RECIPIENT_ENDPOINT 0x02
    #define REQUEST_RECIPIENT_OTHER 0x03

    //****************************************************************************
    //
    // Prototypes for functions exported by the DLL.
    //
    //****************************************************************************
    LMUSB_HANDLE __stdcall InitializeDevice(unsigned short usVID,
    unsigned short usPID,
    LPGUID lpGUID,
    BOOL *pbDriverInstalled);
    LMUSB_HANDLE __stdcall InitializeDeviceByIndex(unsigned short usVID,
    unsigned short usPID,
    LPGUID lpGUID,
    DWORD dwIndex,
    BOOL bOpenDataEndpoints,
    BOOL *pbDriverInstalled);
    BOOL __stdcall TerminateDevice(LMUSB_HANDLE hHandle);
    BOOL __stdcall WriteUSBPacket(LMUSB_HANDLE hHandle,
    unsigned char *pcBuffer,
    unsigned long ulSize,
    unsigned long *pulWritten);
    DWORD __stdcall ReadUSBPacket(LMUSB_HANDLE hHandle,
    unsigned char *pcBuffer,
    unsigned long ulSize,
    unsigned long *pulRead,
    unsigned long ulTimeoutMs,
    HANDLE hBreak);
    BOOL __stdcall Endpoint0Transfer(LMUSB_HANDLE hHandle, UCHAR ucRequestType,
    UCHAR ucRequest, USHORT usValue,
    USHORT usIndex, USHORT usLength,
    PUCHAR pucBuffer, PUSHORT pusCount);

    //****************************************************************************
    //
    // Typedefs for each of the exported functions. This helps if applications
    // want to link the DLL dynamically using LoadLibrary rather than linking
    // directly to the lib file.
    //
    //****************************************************************************
    typedef LMUSB_HANDLE (__stdcall *tInitializeDevice)(unsigned short usVID,
    unsigned short usPID,
    LPGUID lpGUID,
    BOOL *pbDriverInstalled);
    typedef BOOL (__stdcall *tTerminateDevice)(LMUSB_HANDLE hHandle);
    typedef BOOL (__stdcall *tWriteUSBPacket)(LMUSB_HANDLE hHandle,
    unsigned char *pcBuffer,
    unsigned long ulSize,
    unsigned long *pulWritten);
    typedef DWORD (__stdcall *tReadUSBPacket)(LMUSB_HANDLE hHandle,
    unsigned char *pcBuffer,
    unsigned long ulSize,
    unsigned long *pulRead,
    unsigned long ulTimeoutMs,
    HANDLE hBreak);
    typedef DWORD (__stdcall *tEndpoint0Transfer)(LMUSB_HANDLE hHandle,
    UCHAR ucRequestType,
    UCHAR ucRequest, USHORT usValue,
    USHORT usIndex, USHORT usLength,
    PUCHAR pucBuffer,
    PUSHORT pusCount);
    #ifdef __cplusplus
    }
    #endif


    Could you give me a piece of sample code on device and host PC side to connect these two devices? Thanks lot and have a good weekend!

    Ned
  • Hello Ned,

    I do not have a code that can be used. Can you check what is the value being returned by the OpenDeviceByIndex?

    Regards
    Amit
  • Hi Amit,

    Here is the code of USB initialization and test results:

    m_hUSB = NULL;

    m_hUSB = InitializeDeviceByIndex(BULK_VID, BULK_PID, (LPGUID)&(GUID_DEVINTERFACE_TIVA_BULK), 0, TRUE, &bDriverInstalled);

    // m_hUSB = 0x00502648
    // Send echo string and return from device 1

    m_hUSB = NULL;

    m_hUSB = InitializeDeviceByIndex(BULK_VID, BULK_PID, (LPGUID)&(GUID_DEVINTERFACE_TIVA_BULK), 1, TRUE, &bDriverInstalled);

    // m_hUSB = 0x004f3bc0
    // Send echo string and return from device 0

    Thanks!

    Ned
  • Hello Ned

    Since the m_hUSB is not NULL it seems to be returning a handle back.

    Regards
    Amit
  • Hi Amit,

    We could use an alternate way to identify these two devices instead of using the production string in device's descriptors , such as sending a command to device and get different responses. Thanks lots for your great help!

    Best Regards,

    Ned 

  • Hello Ned,

    That would work, but how do you know which device is being accessed over USB?

    Regards
    Amit
  • Hi Amit,

    We can use two handles if we know there are two devices connected, then use each handle to send one command and identify each device from their response.

    Ned
  • Hello Ned,

    But if there are 4 devices connected the software need to scale up. Rather use the single handle to get the devices one by one to see which one matches the required response to command.

    Regards
    Amit
  • HI Amit,

    We need multiple handles to control multiple devices in one system. The host PC software needs to remember which handle for which device.

    Ned
  • Hello Ned,

    OK, that makes sense. I was of the opinion that it was one amongst multiple device.

    Regards
    Amit