String buffers - Devices contribute buffersmain
| // your best effort to read chapter 4 before asking USB questions! | // your best effort to read chapter 4 before asking USB questions! | ||||
| #define USBHOST_PRINT_DEBUG | |||||
| //#define USBHOST_PRINT_DEBUG | |||||
| /************************************************/ | /************************************************/ | ||||
| /* Data Types */ | /* Data Types */ | ||||
| }; | }; | ||||
| } setup_t; | } setup_t; | ||||
| typedef struct { | |||||
| enum {STRING_BUF_SIZE=50}; | |||||
| enum {STR_ID_MAN=0, STR_ID_PROD, STR_ID_SERIAL, STR_ID_CNT}; | |||||
| uint8_t iStrings[STR_ID_CNT]; // Index into array for the three indexes | |||||
| uint8_t buffer[STRING_BUF_SIZE]; | |||||
| } strbuf_t; | |||||
| #define DEVICE_STRUCT_STRING_BUF_SIZE 50 | |||||
| // Device_t holds all the information about a USB device | // Device_t holds all the information about a USB device | ||||
| #define DEVICE_STRUCT_STRING_BUF_SIZE 48 | |||||
| struct Device_struct { | struct Device_struct { | ||||
| Pipe_t *control_pipe; | Pipe_t *control_pipe; | ||||
| Pipe_t *data_pipes; | Pipe_t *data_pipes; | ||||
| Device_t *next; | Device_t *next; | ||||
| USBDriver *drivers; | USBDriver *drivers; | ||||
| strbuf_t *strbuf; | |||||
| uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec | uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec | ||||
| uint8_t address; | uint8_t address; | ||||
| uint8_t hub_address; | uint8_t hub_address; | ||||
| uint16_t idVendor; | uint16_t idVendor; | ||||
| uint16_t idProduct; | uint16_t idProduct; | ||||
| uint16_t LanguageID; | 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 | // Pipe_t holes all information about each USB endpoint/pipe | ||||
| static void contribute_Devices(Device_t *devices, uint32_t num); | static void contribute_Devices(Device_t *devices, uint32_t num); | ||||
| static void contribute_Pipes(Pipe_t *pipes, uint32_t num); | static void contribute_Pipes(Pipe_t *pipes, uint32_t num); | ||||
| static void contribute_Transfers(Transfer_t *transfers, uint32_t num); | static void contribute_Transfers(Transfer_t *transfers, uint32_t num); | ||||
| static void contribute_String_Buffers(strbuf_t *strbuf, uint32_t num); | |||||
| static volatile bool enumeration_busy; | static volatile bool enumeration_busy; | ||||
| private: | private: | ||||
| static void isr(); | static void isr(); | ||||
| static void free_Pipe(Pipe_t *q); | static void free_Pipe(Pipe_t *q); | ||||
| static Transfer_t * allocate_Transfer(void); | static Transfer_t * allocate_Transfer(void); | ||||
| static void free_Transfer(Transfer_t *q); | static void free_Transfer(Transfer_t *q); | ||||
| static strbuf_t * allocate_string_buffer(void); | |||||
| static void free_string_buffer(strbuf_t *strbuf); | |||||
| static bool allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, | static bool allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, | ||||
| uint32_t maxlen, uint32_t interval); | uint32_t maxlen, uint32_t interval); | ||||
| static void add_qh_to_periodic_schedule(Pipe_t *pipe); | static void add_qh_to_periodic_schedule(Pipe_t *pipe); | ||||
| uint16_t idVendor() { return (device != nullptr) ? device->idVendor : 0; } | uint16_t idVendor() { return (device != nullptr) ? device->idVendor : 0; } | ||||
| uint16_t idProduct() { return (device != nullptr) ? device->idProduct : 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; } | |||||
| const uint8_t *manufacturer() | |||||
| { return ((device == nullptr) || (device->strbuf == nullptr)) ? nullptr : &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; } | |||||
| const uint8_t *product() | |||||
| { return ((device == nullptr) || (device->strbuf == nullptr)) ? nullptr : &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; } | |||||
| const uint8_t *serialNumber() | |||||
| { return ((device == nullptr) || (device->strbuf == nullptr)) ? nullptr : &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; } | |||||
| // TODO: user-level functions | // TODO: user-level functions | ||||
| // check if device is bound/active/online | // check if device is bound/active/online | ||||
| // wish to claim any device or interface (eg, if getting data | // wish to claim any device or interface (eg, if getting data | ||||
| // from the HID parser). | // from the HID parser). | ||||
| Device_t *device; | Device_t *device; | ||||
| friend class USBHost; | friend class USBHost; | ||||
| }; | }; | ||||
| operator bool() { return (mydevice != nullptr); } | operator bool() { return (mydevice != nullptr); } | ||||
| uint16_t idVendor() { return (mydevice != nullptr) ? mydevice->idVendor : 0; } | uint16_t idVendor() { return (mydevice != nullptr) ? mydevice->idVendor : 0; } | ||||
| uint16_t idProduct() { return (mydevice != nullptr) ? mydevice->idProduct : 0; } | uint16_t idProduct() { return (mydevice != nullptr) ? mydevice->idProduct : 0; } | ||||
| const uint8_t *manufacturer() | |||||
| { return ((mydevice == nullptr) || (mydevice->strbuf == nullptr)) ? nullptr : &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; } | |||||
| const uint8_t *product() | |||||
| { return ((mydevice == nullptr) || (mydevice->strbuf == nullptr)) ? nullptr : &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; } | |||||
| const uint8_t *serialNumber() | |||||
| { return ((mydevice == nullptr) || (mydevice->strbuf == nullptr)) ? nullptr : &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; } | |||||
| private: | private: | ||||
| virtual bool claim_collection(Device_t *dev, uint32_t topusage); | virtual bool claim_collection(Device_t *dev, uint32_t topusage); | ||||
| virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); | virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); | ||||
| Device_t mydevices[MAXPORTS]; | Device_t mydevices[MAXPORTS]; | ||||
| Pipe_t mypipes[2] __attribute__ ((aligned(32))); | Pipe_t mypipes[2] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| USBDriverTimer debouncetimer; | USBDriverTimer debouncetimer; | ||||
| USBDriverTimer resettimer; | USBDriverTimer resettimer; | ||||
| setup_t setup; | setup_t setup; | ||||
| bool use_report_id; | bool use_report_id; | ||||
| Pipe_t mypipes[3] __attribute__ ((aligned(32))); | Pipe_t mypipes[3] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| }; | }; | ||||
| bool processing_new_data_ = false; | bool processing_new_data_ = false; | ||||
| Pipe_t mypipes[2] __attribute__ ((aligned(32))); | Pipe_t mypipes[2] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| }; | }; | ||||
| class MIDIDevice : public USBDriver { | class MIDIDevice : public USBDriver { | ||||
| void (*handleTimeCodeQuarterFrame)(uint16_t data); | void (*handleTimeCodeQuarterFrame)(uint16_t data); | ||||
| Pipe_t mypipes[3] __attribute__ ((aligned(32))); | Pipe_t mypipes[3] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| }; | }; | ||||
| private: | private: | ||||
| Pipe_t mypipes[3] __attribute__ ((aligned(32))); | Pipe_t mypipes[3] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| USBDriverTimer txtimer; | USBDriverTimer txtimer; | ||||
| uint32_t bigbuffer[(BUFFER_SIZE+3)/4]; | uint32_t bigbuffer[(BUFFER_SIZE+3)/4]; | ||||
| setup_t setup; | setup_t setup; | ||||
| private: | private: | ||||
| Pipe_t mypipes[2] __attribute__ ((aligned(32))); | Pipe_t mypipes[2] __attribute__ ((aligned(32))); | ||||
| Transfer_t mytransfers[3] __attribute__ ((aligned(32))); | Transfer_t mytransfers[3] __attribute__ ((aligned(32))); | ||||
| strbuf_t mystring_bufs[1]; | |||||
| //USBDriverTimer txtimer; | //USBDriverTimer txtimer; | ||||
| USBDriverTimer updatetimer; | USBDriverTimer updatetimer; | ||||
| Pipe_t *rxpipe; | Pipe_t *rxpipe; |
| { | { | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| callbackFunc = NULL; | callbackFunc = NULL; | ||||
| } | } |
| free_Device(dev); | free_Device(dev); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| dev->strbuf = allocate_string_buffer(); // try to allocate a string buffer; | |||||
| dev->control_pipe->callback_function = &enumeration; | dev->control_pipe->callback_function = &enumeration; | ||||
| dev->control_pipe->direction = 1; // 1=IN | dev->control_pipe->direction = 1; // 1=IN | ||||
| // Here is where the enumeration process officially begins. | // Here is where the enumeration process officially begins. | ||||
| dev->enum_state = 4; | dev->enum_state = 4; | ||||
| return; | return; | ||||
| case 4: // parse Language ID | 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) { | if (enumbuf[4] < 4 || enumbuf[5] != 3) { | ||||
| dev->enum_state = 11; | dev->enum_state = 11; | ||||
| } else { | } else { | ||||
| } | } | ||||
| void USBHost::convertStringDescriptorToASCIIString(uint8_t string_index, Device_t *dev, const Transfer_t *transfer) { | void USBHost::convertStringDescriptorToASCIIString(uint8_t string_index, Device_t *dev, const Transfer_t *transfer) { | ||||
| strbuf_t *strbuf = dev->strbuf; | |||||
| if (!strbuf) return; // don't have a buffer | |||||
| uint8_t *buffer = (uint8_t*)transfer->buffer; | uint8_t *buffer = (uint8_t*)transfer->buffer; | ||||
| uint8_t buf_index = string_index? dev->iStrings[string_index]+1 : 0; | |||||
| uint8_t buf_index = string_index? strbuf->iStrings[string_index]+1 : 0; | |||||
| // Try to verify - The first byte should be length and the 2nd byte should be 0x3 | // Try to verify - The first byte should be length and the 2nd byte should be 0x3 | ||||
| if (!buffer || (buffer[1] != 0x3)) { | if (!buffer || (buffer[1] != 0x3)) { | ||||
| return; // No string so can simply return | return; // No string so can simply return | ||||
| } | } | ||||
| dev->iStrings[string_index] = buf_index; // remember our starting positio | |||||
| strbuf->iStrings[string_index] = buf_index; // remember our starting positio | |||||
| uint8_t count_bytes_returned = buffer[0]; | uint8_t count_bytes_returned = buffer[0]; | ||||
| if ((buf_index + count_bytes_returned/2) >= DEVICE_STRUCT_STRING_BUF_SIZE) | if ((buf_index + count_bytes_returned/2) >= DEVICE_STRUCT_STRING_BUF_SIZE) | ||||
| count_bytes_returned = (DEVICE_STRUCT_STRING_BUF_SIZE - buf_index) * 2; | count_bytes_returned = (DEVICE_STRUCT_STRING_BUF_SIZE - buf_index) * 2; | ||||
| // Now copy into our storage buffer. | // 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) { | 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]; | |||||
| strbuf->buffer[buf_index++] = buffer[i]; | |||||
| } | } | ||||
| dev->string_buf[buf_index] = 0; // null terminate. | |||||
| strbuf->buffer[buf_index] = 0; // null terminate. | |||||
| // Update other indexes to point to null character | // Update other indexes to point to null character | ||||
| while (++string_index < 3) { | while (++string_index < 3) { | ||||
| dev->iStrings[string_index] = buf_index; // point to trailing NULL character | |||||
| strbuf->iStrings[string_index] = buf_index; // point to trailing NULL character | |||||
| } | } | ||||
| } | } | ||||
| prev_dev->next = p->next; | prev_dev->next = p->next; | ||||
| } | } | ||||
| println("removed Device_t from devlist"); | println("removed Device_t from devlist"); | ||||
| if (p->strbuf != nullptr ) { | |||||
| free_string_buffer(p->strbuf); | |||||
| } | |||||
| free_Device(p); | free_Device(p); | ||||
| break; | break; | ||||
| } | } |
| USBHub hub1(myusb); | USBHub hub1(myusb); | ||||
| USBHub hub2(myusb); | USBHub hub2(myusb); | ||||
| USBHub hub3(myusb); | USBHub hub3(myusb); | ||||
| USBHub hub4(myusb); | |||||
| KeyboardController keyboard1(myusb); | KeyboardController keyboard1(myusb); | ||||
| KeyboardController keyboard2(myusb); | KeyboardController keyboard2(myusb); | ||||
| KeyboardHIDExtrasController hidextras(myusb); | KeyboardHIDExtrasController hidextras(myusb); | ||||
| MouseController mouse1(myusb); | MouseController mouse1(myusb); | ||||
| JoystickController joystick1(myusb); | JoystickController joystick1(myusb); | ||||
| USBDriver *drivers[] = {&hub1, &hub2, &hub3, &keyboard1, &keyboard2, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
| #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[1])) | |||||
| const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2","Hub3", "KB1", "KB2", "HID1", "HID2", "HID3", "HID4", "HID5" }; | |||||
| USBDriver *drivers[] = {&hub1, &hub2, &hub3, &hub4, &keyboard1, &keyboard2, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
| #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
| const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "Hub3", "Hub4" "KB1", "KB2", "HID1", "HID2", "HID3", "HID4", "HID5" }; | |||||
| bool driver_active[CNT_DEVICES] = {false, false, false, false}; | bool driver_active[CNT_DEVICES] = {false, false, false, false}; | ||||
| // Lets also look at HID Input devices | |||||
| USBHIDInput *hiddrivers[] = {&mouse1, &joystick1}; | |||||
| #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | |||||
| const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1"}; | |||||
| bool hid_driver_active[CNT_DEVICES] = {false, false}; | |||||
| void setup() | void setup() | ||||
| { | { | ||||
| while (!Serial) ; // wait for Arduino Serial Monitor | while (!Serial) ; // wait for Arduino Serial Monitor | ||||
| Serial.println("\n\nUSB Host Testing"); | Serial.println("\n\nUSB Host Testing"); | ||||
| Serial.println(sizeof(USBHub), DEC); | |||||
| myusb.begin(); | myusb.begin(); | ||||
| keyboard1.attachPress(OnPress); | keyboard1.attachPress(OnPress); | ||||
| keyboard2.attachPress(OnPress); | keyboard2.attachPress(OnPress); | ||||
| } | } | ||||
| } | } | ||||
| for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) { | |||||
| if (*hiddrivers[i] != hid_driver_active[i]) { | |||||
| if (hid_driver_active[i]) { | |||||
| Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]); | |||||
| hid_driver_active[i] = false; | |||||
| } else { | |||||
| Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||||
| hid_driver_active[i] = true; | |||||
| const uint8_t *psz = hiddrivers[i]->manufacturer(); | |||||
| if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||||
| psz = hiddrivers[i]->product(); | |||||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||||
| psz = hiddrivers[i]->serialNumber(); | |||||
| if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
| } | |||||
| } | |||||
| } | |||||
| if(mouse1.available()) { | if(mouse1.available()) { | ||||
| Serial.print("Mouse: buttons = "); | Serial.print("Mouse: buttons = "); | ||||
| Serial.print(mouse1.getButtons()); | Serial.print(mouse1.getButtons()); |
| { | { | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||
| contribute_Devices(mydevices, sizeof(mydevices)/sizeof(Device_t)); | contribute_Devices(mydevices, sizeof(mydevices)/sizeof(Device_t)); | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||
| { | { | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||
| static Device_t * free_Device_list = NULL; | static Device_t * free_Device_list = NULL; | ||||
| static Pipe_t * free_Pipe_list = NULL; | static Pipe_t * free_Pipe_list = NULL; | ||||
| static Transfer_t * free_Transfer_list = NULL; | static Transfer_t * free_Transfer_list = NULL; | ||||
| static strbuf_t * free_strbuf_list = NULL; | |||||
| // A small amount of non-driver memory, just to get things started | // A small amount of non-driver memory, just to get things started | ||||
| // TODO: is this really necessary? Can these be eliminated, so we | // TODO: is this really necessary? Can these be eliminated, so we | ||||
| // use only memory from the drivers? | // use only memory from the drivers? | ||||
| free_Transfer_list = transfer; | free_Transfer_list = transfer; | ||||
| } | } | ||||
| strbuf_t * USBHost::allocate_string_buffer(void) | |||||
| { | |||||
| strbuf_t *strbuf = free_strbuf_list; | |||||
| if (strbuf) { | |||||
| free_strbuf_list = *(strbuf_t **)strbuf; | |||||
| strbuf->iStrings[strbuf_t::STR_ID_MAN] = 0; // Set indexes into string buffer to say not there... | |||||
| strbuf->iStrings[strbuf_t::STR_ID_PROD] = 0; | |||||
| strbuf->iStrings[strbuf_t::STR_ID_SERIAL] = 0; | |||||
| strbuf->buffer[0] = 0; // have trailing NULL.. | |||||
| } | |||||
| return strbuf; | |||||
| } | |||||
| void USBHost::free_string_buffer(strbuf_t *strbuf) | |||||
| { | |||||
| *(strbuf_t **)strbuf = free_strbuf_list; | |||||
| free_strbuf_list = strbuf; | |||||
| } | |||||
| void USBHost::contribute_Devices(Device_t *devices, uint32_t num) | void USBHost::contribute_Devices(Device_t *devices, uint32_t num) | ||||
| { | { | ||||
| Device_t *end = devices + num; | Device_t *end = devices + num; | ||||
| } | } | ||||
| } | } | ||||
| void USBHost::contribute_String_Buffers(strbuf_t *strbufs, uint32_t num) | |||||
| { | |||||
| strbuf_t *end = strbufs + num; | |||||
| for (strbuf_t *str = strbufs ; str < end; str++) { | |||||
| free_string_buffer(str); | |||||
| } | |||||
| } | |||||
| { | { | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| handleNoteOff = NULL; | handleNoteOff = NULL; | ||||
| handleNoteOn = NULL; | handleNoteOn = NULL; | ||||
| handleVelocityChange = NULL; | handleVelocityChange = NULL; |
| { | { | ||||
| contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
| contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t)); | ||||
| contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | |||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| } | } | ||||