USBHost_t36 attach/detach callbacks

Status
Not open for further replies.

SteveBar

Well-known member
HI All,
I really wanted to get "call backs" when USB devices attached and detached, so a buddy helped me add some code to USBHost_t36.h and enumeration.cpp...

The 1st goal was so no polling needs to be done for the code to know when a device attaches and detaches.
The 2nd goal was to associate the midi_Host(1-4) objects with the physical ports. There is a 4 port hub built into my device. This works well using the "hub_port" data, but only if no 2nd tier hub is plugged in. Also the chaining of hubs creates 'n' tiers. And I have not found a way to discern which devices are on which tiers, any help would be greatly appreciated.

Example defs...
MIDIDevice midi_Host1(myUSB_Host);
MIDIDevice midi_Host2(myUSB_Host);
MIDIDevice midi_Host3(myUSB_Host);
MIDIDevice midi_Host4(myUSB_Host);

Paul, it would be great if you would include this code in the USBHost_t36 lib! :) It is really handy when working with USB MIDI devices. I'm not a Github jockey but I would be happy to send you the modified files, if you'd like.

Here is a nice description of the difference between the physical topography and logical topography of USB devices and hubs.


The code snippits below show some of the surrounding code from the original USBHost_t36 lib files so you 'll know where to paste the new code.

In USBHost_t36.h two functions are defined to set the call-back function pointers, setAttachCallback and setDetachCallback.

Code:
//snippit...
class USBHost {
public:
	static void begin();
	static void Task();
	static void countFree(uint32_t &devices, uint32_t &pipes, uint32_t &trans, uint32_t &strs);

	// Added by Conductive Labs LLC to add call-back that a USB device attach/detach
	static void setAttachCallback(attachCallback attachHandler);
	static void setDetachCallback(detachCallback detachHandler);


Just above the class definitin for USBHost, the typedef's where added.
Code:
//snippit...
struct Transfer_struct {
        // removed code...
};

// Added by Conductive Labs LLC to add call-back that a USB device attach/detach
typedef void (*attachCallback)(Device_t* device);
typedef void (*detachCallback)(Device_t* device);


Towards the top of the the file enumeration.cpp the vars to store the pointers are declared and the actual "set" functions are added (setAttachCallback and setDetachCallback).
Code:
//snippit...
#define print   USBHost::print_
#define println USBHost::println_

// Added by Conductive Labs LLC to add call-back that a USB device attach/detach
attachCallback gAttachHandler = nullptr;
detachCallback gDetachHandler = nullptr;

void USBHost::setAttachCallback(attachCallback attachHandler) {
	gAttachHandler = attachHandler;
}

void USBHost::setDetachCallback(detachCallback detachHandler) {
	gDetachHandler = detachHandler;
}

Last but not least the "attached" callback is being made here. Note the function returns the pointer to the device info "Device_struct".
Code:
case 14: // device is now configured
	claim_drivers(dev);
	dev->enum_state = 15;
	// unlock exclusive access to enumeration process.  If any
	// more devices are waiting, the hub driver is responsible
	// for resetting their ports and starting their enumeration
	// when the port enables.
	USBHost::enumeration_busy = false;
	
	// Added by Conductive Labs LLC to notify registered call-back that a USB device attached
	// returns handle to device struct "Device_struct"
	if (gAttachHandler) {
			gAttachHandler(dev);
	}

...and the "detached" callback is being made here. Note the function returns the pointer to the device info "Device_struct".
Code:
// remove device from devlist and free its Device_t
Device_t *prev_dev = NULL;
for (Device_t *p = devlist; p; p = p->next) {
	if (p == dev) {
		if (prev_dev == NULL) {
			devlist = p->next;
		} else {
			prev_dev->next = p->next;
		}
		println("removed Device_t from devlist");
		
		// Added by Conductive Labs LLC to notify registered call-back that a USB device dattached
		// returns handle to device struct "Device_struct"
		if (gDetachHandler) {
			gDetachHandler(dev);
		}
		
		if (p->strbuf != nullptr ) {
			free_string_buffer(p->strbuf);
		}
		free_Device(p);
		break;
	}
	prev_dev = p;
}

Here is the code in my app that prints the info to the serial port when the call back is received... I'll be adding code here to maintain record of which USB devices are attached at any given time.
Code:
void AttachedUSBDevice(Device_t* device) {
        
    Serial.print("NEW USB Device ("); 
    Serial.print(device->idVendor); 
    Serial.print(String("/") + device->idProduct + "):"); 

    Serial.print(String(" ") + device->address);
    Serial.print(String("-") + device->hub_port);
    Serial.print(String("-") + device->hub_address); 
    

    Serial.print(String("  C:") + device->bDeviceClass); 
    Serial.print(String("-") + device->bDeviceSubClass); 
    
    Device_t *dev = *(Device_t * volatile *)&device;
    
    String prod = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
    Serial.print(String("  Co: ") + prod );
    
    String manu = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
    Serial.print(String("'s ") + manu );
    
    String seri = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
    Serial.println(String(" #") + seri );
        
 
    /*
    // From file USBHost_t36.h - all the data available about the USB devices
    // Device_t holds all the information about a USB device
    struct Device_struct {
      Pipe_t   *control_pipe;
      Pipe_t   *data_pipes;
      Device_t *next;
      USBDriver *drivers;
      strbuf_t *strbuf;
      uint8_t  speed; // 0=12, 1=1.5, 2=480 Mbit/sec
      uint8_t  address;
      uint8_t  hub_address;
      uint8_t  hub_port;
      uint8_t  enum_state;
      uint8_t  bDeviceClass;
      uint8_t  bDeviceSubClass;
      uint8_t  bDeviceProtocol;
      uint8_t  bmAttributes;
      uint8_t  bMaxPower;
      uint16_t idVendor;
      uint16_t idProduct;
      uint16_t LanguageID;
    }
    */
      
} // end fcn AttachedUSBDevice

  
void DetachedUSBDevice(Device_t* device) {

    Serial.print("USB Dev Detached (");
    Serial.print(device->idVendor); 
    Serial.print(String("/") + device->idProduct + "):"); 

    Serial.print(String(" ") + device->address);
    Serial.print(String("-") + device->hub_port);
    Serial.print(String("-") + device->hub_address); 

    Serial.print(String("  C:") + device->bDeviceClass); 
    Serial.print(String("-") + device->bDeviceSubClass); 
    
    Device_t *dev = *(Device_t * volatile *)&device;
    
    String prod = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
    Serial.print(String(" Co: ") + prod );
    
    String manu = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
    Serial.print(String("'s ") + manu );
    
    String seri = (char*) &dev->strbuf->buffer[dev->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
    Serial.println(String(" #") + seri );

} // end fcn DetachedUSBDevice
 
Last edited:
Status
Not open for further replies.
Back
Top