WIP - Add Strings to device structure

Added the ability to query the
Manufactur, product name and serial number strings from a device.

WIP - Eats up lots of memory, next up experiment move from Device_t object to maybe top level objects.  Probably fewer than them as each hub allocates something like 7 Device objects
This commit is contained in:
Kurt Eckhardt 2017-10-14 14:27:09 -07:00
parent 03a7150872
commit 40cb6322ac
3 changed files with 49 additions and 2 deletions

View File

@ -141,6 +141,7 @@ typedef union {
} setup_t;
// Device_t holds all the information about a USB device
#define DEVICE_STRUCT_STRING_BUF_SIZE 48
struct Device_struct {
Pipe_t *control_pipe;
Pipe_t *data_pipes;
@ -159,6 +160,8 @@ struct Device_struct {
uint16_t idVendor;
uint16_t idProduct;
uint16_t LanguageID;
uint8_t string_buf[DEVICE_STRUCT_STRING_BUF_SIZE]; // Probably want a place to allocate fewer of these...
uint8_t iStrings[3]; // 3 indexes - vendor string, product string, serial number.
};
// Pipe_t holes all information about each USB endpoint/pipe
@ -248,6 +251,7 @@ protected:
static volatile bool enumeration_busy;
private:
static void isr();
static void convertStringDescriptorToASCIIString(uint8_t string_index, Device_t *dev, const Transfer_t *transfer);
static void claim_drivers(Device_t *dev);
static uint32_t assign_address(void);
static bool queue_Transfer(Pipe_t *pipe, Transfer_t *transfer);
@ -350,6 +354,11 @@ public:
operator bool() { return (device != nullptr); }
uint16_t idVendor() { return (device != nullptr) ? device->idVendor : 0; }
uint16_t idProduct() { return (device != nullptr) ? device->idProduct : 0; }
const uint8_t *manufacturer() { return (device != nullptr) ? &(device->string_buf[device->iStrings[0]]) : nullptr; }
const uint8_t *product() { return (device != nullptr) ? &(device->string_buf[device->iStrings[1]]) : nullptr; }
const uint8_t *serialNumber() { return (device != nullptr) ? &(device->string_buf[device->iStrings[2]]) : nullptr; }
// TODO: user-level functions
// check if device is bound/active/online
// query vid, pid

View File

@ -201,6 +201,10 @@ void USBHost::enumeration(const Transfer_t *transfer)
dev->enum_state = 4;
return;
case 4: // parse Language ID
dev->iStrings[0] = 0; // Set indexes into string buffer to say not there...
dev->iStrings[1] = 0;
dev->iStrings[2] = 0;
dev->string_buf[0] = 0; // have trailing NULL..
if (enumbuf[4] < 4 || enumbuf[5] != 3) {
dev->enum_state = 11;
} else {
@ -218,6 +222,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
dev->enum_state = 6;
return;
case 6: // parse Manufacturer string
convertStringDescriptorToASCIIString(0, dev, transfer);
// TODO: receive the string...
if (enumbuf[1]) dev->enum_state = 7;
else if (enumbuf[2]) dev->enum_state = 9;
@ -230,7 +235,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
dev->enum_state = 8;
return;
case 8: // parse Product string
// TODO: receive the string...
convertStringDescriptorToASCIIString(1, dev, transfer);
if (enumbuf[2]) dev->enum_state = 9;
else dev->enum_state = 11;
break;
@ -241,7 +246,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
dev->enum_state = 10;
return;
case 10: // parse Serial Number string
// TODO: receive the string...
convertStringDescriptorToASCIIString(2, dev, transfer);
dev->enum_state = 11;
break;
case 11: // request first 9 bytes of config desc
@ -286,6 +291,33 @@ void USBHost::enumeration(const Transfer_t *transfer)
}
}
void USBHost::convertStringDescriptorToASCIIString(uint8_t string_index, Device_t *dev, const Transfer_t *transfer) {
uint8_t *buffer = (uint8_t*)transfer->buffer;
uint8_t buf_index = string_index? dev->iStrings[string_index]+1 : 0;
// Try to verify - The first byte should be length and the 2nd byte should be 0x3
if (!buffer || (buffer[1] != 0x3)) {
return; // No string so can simply return
}
dev->iStrings[string_index] = buf_index; // remember our starting positio
uint8_t count_bytes_returned = buffer[0];
if ((buf_index + count_bytes_returned/2) >= DEVICE_STRUCT_STRING_BUF_SIZE)
count_bytes_returned = (DEVICE_STRUCT_STRING_BUF_SIZE - buf_index) * 2;
// Now copy into our storage buffer.
for (uint8_t i = 2; (i < count_bytes_returned) && (buf_index < (DEVICE_STRUCT_STRING_BUF_SIZE -1)); i += 2) {
dev->string_buf[buf_index++] = buffer[i];
}
dev->string_buf[buf_index] = 0; // null terminate.
// Update other indexes to point to null character
while (++string_index < 3) {
dev->iStrings[string_index] = buf_index; // point to trailing NULL character
}
}
void USBHost::claim_drivers(Device_t *dev)
{
USBDriver *driver, *prev=NULL;

View File

@ -49,6 +49,12 @@ void loop()
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
driver_active[i] = true;
const uint8_t *psz = drivers[i]->manufacturer();
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
psz = drivers[i]->product();
if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
}
}
}