USB game pad + mbed +pc?

22 May 2012

Im kind of confused looking at the notes and libs for USB hosting of devices on mbed.

seems like it can not act as a host device ( drive a USB game controller) AND be hooked to the pc to output the data to a terminal program? or am i very confused. i used BlueUSB and hooked the game pad up it does show the ID and show it as kooked but i cant seem to get a reading from it or see it in the device manager.

or am i going about this all wrong?

thanks for any input.

P.S. for thos who want to know i am trying to hook a Nordic NRF24L01p with the mbed with a USB game pad to send the game pads sticks/button data to the recieving

Nrf24l01p on an arduino. i have them both talking now i just need to get the game pad hooked up. ( hopefuly i can also keep it hooked to the pc to see the data and

get readings back and use like Prossessing or python to augment it. I have the MinIMU-9 + Locosys GSP on the arduino with the nordic with some motor controller.

22 May 2012

Hello Cyric, I think I can help You. If You use DualShock 3 gamepad You will need to use BlueUSB PS3 from Bart Janssens http://mbed.org/users/BartJanssens/programs/PS3_BlueUSB/lq9h2h which is modified BlueUSB from Peter Barrett http://mbed.org/users/peterbarrett1967/programs/BlueUSB/5yn1q which I assume You used.

If You have common USB HID gamepad You will need to modify AutoEvents.cpp file in BlueUSB program. This program checks USB device class...subclass, protocol and starts callback for pre-defined classes. Gamepad, mouse, keyboard are all HID USB devices so to determine which one it is, subclass and protocol are checked. Keyboard is 3,1,1 - mouse 3,1,2 and gamepad is 3,0,0 (class, subclass, protocol) and if You look to AutoEvents.cpp, there are only mouse and keyboard defined.

Overwrite content of that file with this:


/*
Copyright (c) 2010 Peter Barrett

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "mbed.h"
#include "USBHost.h"
#include "Utils.h"

#define AUTOEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol)

#define AUTO_KEYBOARD AUTOEVT(CLASS_HID,1,1)
#define AUTO_MOUSE AUTOEVT(CLASS_HID,1,2)
#define AUTO_GAMEPAD AUTOEVT(CLASS_HID,0,0)


u8 auto_mouse[4];       // buttons,dx,dy,scroll
u8 auto_keyboard[8];    // modifiers,reserved,keycode1..keycode6
u8 auto_gamepad[6];    // x,y,buttons,dpad

void AutoEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
{
    int evt = (int)userData;
    switch (evt)
    {
        case AUTO_KEYBOARD:
            printf("AUTO_KEYBOARD ");
            break;
        case AUTO_MOUSE:
            printf("AUTO_MOUSE ");
            break;
        case AUTO_GAMEPAD:
            printf("AUTO_GAMEPAD "); 
            break;    
            
            
        default:
            printf("HUH ");
    }
    printfBytes("data",data,len);
    USBInterruptTransfer(device,endpoint,data,len,AutoEventCallback,userData);
}

//  Establish transfers for interrupt events
void AddAutoEvent(int device, InterfaceDescriptor* id, EndpointDescriptor* ed)
{
    if ((ed->bmAttributes & 3) != ENDPOINT_INTERRUPT || !(ed->bEndpointAddress & 0x80))
        return;
    
    // Make automatic interrupt enpoints for known devices
    u32 evt = AUTOEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol);
    u8* dst = 0;
    int len;
    switch (evt)
    {
        case AUTO_MOUSE:
            dst = auto_mouse;
            len = sizeof(auto_mouse);
            break;
        case AUTO_KEYBOARD:
            dst = auto_keyboard;
            len = sizeof(auto_keyboard);
            break;
        case AUTO_GAMEPAD:
            dst = auto_gamepad;
            len = sizeof(auto_gamepad);
        default:
            printf("Interrupt endpoint %02X %08X\n",ed->bEndpointAddress,evt);
            break;
    }
    if (dst)
    {
        printf("Auto Event for %02X %08X\n",ed->bEndpointAddress,evt);
        USBInterruptTransfer(device,ed->bEndpointAddress,dst,len,AutoEventCallback,(void*)evt);
    }
}

void PrintString(int device, int i)
{
    u8 buffer[256];
    int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,i,buffer,255);
    if (le < 0)
         return;
    char* dst = (char*)buffer;
    for (int j = 2; j < le; j += 2)
        *dst++ = buffer[j];
    *dst = 0;
    printf("%d:%s\n",i,(const char*)buffer);
 }
 
//  Walk descriptors and create endpoints for a given device
int StartAutoEvent(int device, int configuration, int interfaceNumber)
{
    u8 buffer[255];
    int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255);
    if (err < 0)
        return err;

    int len = buffer[2] | (buffer[3] << 8);
    u8* d = buffer;
    u8* end = d + len;
    while (d < end)
    {
        if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
        {
            InterfaceDescriptor* id = (InterfaceDescriptor*)d;
            if (id->bInterfaceNumber == interfaceNumber)
            {
                 d += d[0];
                while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
                {
                    if (d[1] == DESCRIPTOR_TYPE_ENDPOINT)
                        AddAutoEvent(device,id,(EndpointDescriptor*)d);
                    d += d[0];
                }
            }
        }
        d += d[0];
    }
    return 0;
}

//  Implemented in main.cpp
int OnDiskInsert(int device);

//  Implemented in TestShell.cpp
int OnBluetoothInsert(int device);

void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc)
{
    printf("LoadDevice %d %02X:%02X:%02X\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol);
    char s[128];
    for (int i = 1; i < 3; i++)
    {
        if (GetString(device,i,s,sizeof(s)) < 0)
            break;
        printf("%d: %s\n",i,s);
    }
    
    switch (interfaceDesc->bInterfaceClass)
    {
        case CLASS_MASS_STORAGE:
            if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50)
                OnDiskInsert(device);    // it's SCSI!
            break;
        case CLASS_WIRELESS_CONTROLLER:
            if (interfaceDesc->bInterfaceSubClass == 0x01 && interfaceDesc->bInterfaceProtocol == 0x01)
                OnBluetoothInsert(device);    // it's bluetooth!
            break;
        default:
            StartAutoEvent(device,1,0);
            break;
    }
}


If You look at line 37 there is declared "buffer" for gamepad reports. Here is 6 bytes in length as most common for gamepad with 2 analog sticks, Dpad and 12 buttons.

You can use Simple HIDwrite utility on PC to check length of report Your gamepad has http://www.lvr.com/files/SimpleHIDWrite3.zip Select Your gamepad in list, click info and look for Report size - Input. This size includes report id so size of "buffer" for gamepad reports on line 37 will be this number in Simple HIDwrite-1 byte.

Do not forget to check end of Main.cpp file where is serial port speed defined (here in BlueUSB it is 460800 baud) so terminal must have set same speed.

There also have to be 10K pull-down resistor between D+ pin and GND, also 10K pull-down resistor between D- pin and GND to tell mbed to be in USB host mode.

Also check Peter Barrett's BlueUSB notebook page http://mbed.org/users/peterbarrett1967/notebook/blueusb---bluetooth-and-usb-host-controller-for-mb/ If You missed it.

I hope this can help You little bit.

23 May 2012

Wow thanks for the response. ok i cut and past the new code and then ran SimpleHIDwrite and found my gamepad (using Anko corp, Gemini indistries, HID-C??|, Input:8 Output:3 Feature:0) so i changed the buffer to 7? (8 from the SHW Input and -1 for the report id?) and thats cool and all but can i/should i also see it in my windows device manager under HID Devices?