- use CFG_TUH_MIDI as number of midi host instance
- comment out tuh_descriptor_device_cb/tuh_desc_configuration_cb since it is unrelated to this PR
This commit is contained in:
		| @@ -36,14 +36,6 @@ | ||||
| //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF | ||||
| //--------------------------------------------------------------------+ | ||||
| #ifndef CFG_TUH_MAX_CABLES | ||||
|   #define CFG_TUH_MAX_CABLES 16 | ||||
| #endif | ||||
| #define CFG_TUH_MIDI_RX_BUFSIZE 64 | ||||
| #define CFG_TUH_MIDI_TX_BUFSIZE 64 | ||||
| #ifndef CFG_TUH_MIDI_EP_BUFSIZE | ||||
|   #define CFG_TUH_MIDI_EP_BUFSIZE 64 | ||||
| #endif | ||||
|  | ||||
| // TODO: refactor to share code with the MIDI Device driver | ||||
| typedef struct | ||||
| @@ -117,34 +109,44 @@ typedef struct | ||||
| #endif | ||||
| }midih_interface_t; | ||||
|  | ||||
| static midih_interface_t _midi_host[CFG_TUH_DEVICE_MAX]; | ||||
|  | ||||
| static midih_interface_t *get_midi_host(uint8_t dev_addr) | ||||
| { | ||||
|   TU_VERIFY(dev_addr >0 && dev_addr <= CFG_TUH_DEVICE_MAX); | ||||
|   return (_midi_host + dev_addr - 1); | ||||
| } | ||||
| static midih_interface_t _midi_host[CFG_TUH_MIDI]; | ||||
|  | ||||
| //------------- Internal prototypes -------------// | ||||
| static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Helper | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_midi_by_daddr(uint8_t dev_addr) { | ||||
|   for (uint8_t i = 0; i < CFG_TUH_MIDI; i++) { | ||||
|     if (_midi_host[i].dev_addr == dev_addr) { | ||||
|       return &_midi_host[i]; | ||||
|     } | ||||
|   } | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_new_midi(void) { | ||||
|   return find_midi_by_daddr(0); | ||||
| } | ||||
|  | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // USBH API | ||||
| //--------------------------------------------------------------------+ | ||||
| bool midih_init(void) | ||||
| { | ||||
| bool midih_init(void) { | ||||
|   tu_memclr(&_midi_host, sizeof(_midi_host)); | ||||
|   // config fifos | ||||
|   for (int inst = 0; inst < CFG_TUH_DEVICE_MAX; inst++) | ||||
|   { | ||||
|   for (int inst = 0; inst < CFG_TUH_MIDI; inst++) { | ||||
|     midih_interface_t *p_midi_host = &_midi_host[inst]; | ||||
|     tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false); // true, true | ||||
|     tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false); // OBVS. | ||||
|     tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false);// true, true | ||||
|     tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false);// OBVS. | ||||
|  | ||||
|   #if CFG_FIFO_MUTEX | ||||
|     #if CFG_FIFO_MUTEX | ||||
|     tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex)); | ||||
|     tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); | ||||
|   #endif | ||||
|     #endif | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
| @@ -152,7 +154,7 @@ bool midih_init(void) | ||||
| bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) | ||||
| { | ||||
|   (void)result; | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   if ( ep_addr == p_midi_host->ep_in) | ||||
|   { | ||||
| @@ -211,13 +213,14 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| void midih_close(uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   if (p_midi_host == NULL) | ||||
| void midih_close(uint8_t dev_addr) { | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   if (p_midi_host == NULL) { | ||||
|     return; | ||||
|   if (tuh_midi_umount_cb) | ||||
|   } | ||||
|   if (tuh_midi_umount_cb) { | ||||
|     tuh_midi_umount_cb(dev_addr, 0); | ||||
|   } | ||||
|   tu_fifo_clear(&p_midi_host->rx_ff); | ||||
|   tu_fifo_clear(&p_midi_host->tx_ff); | ||||
|   p_midi_host->ep_in = 0; | ||||
| @@ -240,24 +243,24 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d | ||||
| { | ||||
|   (void) rhport; | ||||
|  | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|  | ||||
|   midih_interface_t *p_midi_host = find_new_midi(); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|  | ||||
|   p_midi_host->num_string_indices = 0; | ||||
|   TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); | ||||
|   // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface | ||||
|   uint8_t const *p_desc = (uint8_t const *) desc_itf; | ||||
|   uint16_t len_parsed = 0; | ||||
|   if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) | ||||
|   { | ||||
|   if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { | ||||
|     // Keep track of any string descriptor that might be here | ||||
|     if (desc_itf->iInterface != 0) | ||||
|         p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; | ||||
|     if (desc_itf->iInterface != 0) { | ||||
|       p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; | ||||
|     } | ||||
|     // This driver does not support audio streaming. However, if this is the audio control interface | ||||
|     // there might be a MIDI interface following it. Search through every descriptor until a MIDI | ||||
|     // interface is found or the end of the descriptor is found | ||||
|     while (len_parsed < max_len && (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) | ||||
|     { | ||||
|     while (len_parsed < max_len && | ||||
|           (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) { | ||||
|       len_parsed += desc_itf->bLength; | ||||
|       p_desc = tu_desc_next(p_desc); | ||||
|       desc_itf = (tusb_desc_interface_t const *)p_desc; | ||||
| @@ -269,8 +272,9 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d | ||||
|   len_parsed += desc_itf->bLength; | ||||
|  | ||||
|   // Keep track of any string descriptor that might be here | ||||
|   if (desc_itf->iInterface != 0) | ||||
|       p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; | ||||
|   if (desc_itf->iInterface != 0) { | ||||
|     p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; | ||||
|   } | ||||
|  | ||||
|   p_desc = tu_desc_next(p_desc); | ||||
|   TU_LOG1("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); | ||||
| @@ -282,195 +286,169 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d | ||||
|   // assume it is an interface header | ||||
|   midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; | ||||
|   TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || | ||||
|     (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || | ||||
|     p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); | ||||
|             (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || | ||||
|             p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); | ||||
|  | ||||
|   uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor | ||||
|   p_midi_host->itf_num = desc_itf->bInterfaceNumber; | ||||
|   tusb_desc_endpoint_t const* in_desc = NULL; | ||||
|   tusb_desc_endpoint_t const* out_desc = NULL; | ||||
|   while (len_parsed < max_len) | ||||
|   { | ||||
|   while (len_parsed < max_len) { | ||||
|     TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || | ||||
|       (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || | ||||
|       p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); | ||||
|               (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || | ||||
|               p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); | ||||
|  | ||||
|     if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) { | ||||
|       // The USB host doesn't really need this information unless it uses | ||||
|       // the string descriptor for a jack or Element | ||||
|  | ||||
|       // assume it is an input jack | ||||
|       midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *)p_desc; | ||||
|       if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) | ||||
|       { | ||||
|       midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *) p_desc; | ||||
|       if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) { | ||||
|         TU_LOG2("Found MIDI Interface Header\r\b"); | ||||
|       } | ||||
|       else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) | ||||
|       { | ||||
|       } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { | ||||
|         // Then it is an in jack. | ||||
|         TU_LOG2("Found in jack\r\n"); | ||||
| #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         if (p_midi_host->next_in_jack < MAX_IN_JACKS) | ||||
|         { | ||||
|   #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         if (p_midi_host->next_in_jack < MAX_IN_JACKS) { | ||||
|           p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_id = p_mdij->bJackID; | ||||
|           p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_type = p_mdij->bJackType; | ||||
|           p_midi_host->in_jack_info[p_midi_host->next_in_jack].string_index = p_mdij->iJack; | ||||
|           ++p_midi_host->next_in_jack; | ||||
|           // Keep track of any string descriptor that might be here | ||||
|           if (p_mdij->iJack != 0) | ||||
|           if (p_mdij->iJack != 0) { | ||||
|             p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdij->iJack; | ||||
|  | ||||
|           } | ||||
|         } | ||||
| #endif | ||||
|       } | ||||
|       else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) | ||||
|       { | ||||
|   #endif | ||||
|       } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) { | ||||
|         // then it is an out jack | ||||
|         TU_LOG2("Found out jack\r\n"); | ||||
| #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         if (p_midi_host->next_out_jack < MAX_OUT_JACKS) | ||||
|         { | ||||
|           midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *)p_desc; | ||||
|   #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         if (p_midi_host->next_out_jack < MAX_OUT_JACKS) { | ||||
|           midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *) p_desc; | ||||
|           p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; | ||||
|           p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; | ||||
|           p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; | ||||
|           const struct associated_jack_s { | ||||
|               uint8_t id; | ||||
|               uint8_t pin; | ||||
|           } *associated_jack = (const struct associated_jack_s *)(p_desc+6); | ||||
|             uint8_t id; | ||||
|             uint8_t pin; | ||||
|           } *associated_jack = (const struct associated_jack_s *) (p_desc + 6); | ||||
|           int jack; | ||||
|           for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) | ||||
|           { | ||||
|           for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) { | ||||
|             p_midi_host->out_jack_info[p_midi_host->next_out_jack].source_ids[jack] = associated_jack->id; | ||||
|           } | ||||
|           p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc+6+p_mdoj->bNrInputPins*2); | ||||
|           p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc + 6 + p_mdoj->bNrInputPins * 2); | ||||
|           ++p_midi_host->next_out_jack; | ||||
|           if (p_mdoj->iJack != 0) | ||||
|           if (p_mdoj->iJack != 0) { | ||||
|             p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdoj->iJack; | ||||
|           } | ||||
|         } | ||||
| #endif | ||||
|       } | ||||
|       else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) | ||||
|       { | ||||
|   #endif | ||||
|       } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) { | ||||
|         // the it is an element; | ||||
|     #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|   #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         TU_LOG1("Found element; strings not supported\r\n"); | ||||
|     #else | ||||
|   #else | ||||
|         TU_LOG2("Found element\r\n"); | ||||
|     #endif | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|   #endif | ||||
|       } else { | ||||
|         TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); | ||||
|         TU_VERIFY(false); // unknown CS Interface sub-type | ||||
|         TU_VERIFY(false);// unknown CS Interface sub-type | ||||
|       } | ||||
|       len_parsed += p_mdij->bLength; | ||||
|     } | ||||
|     else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) | ||||
|     { | ||||
|     } else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) { | ||||
|       TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); | ||||
|       TU_VERIFY(prev_ep_addr != 0); | ||||
|       // parse out the mapping between the device's embedded jacks and the endpoints | ||||
|       // Each embedded IN jack is associated with an OUT endpoint | ||||
|       midi_cs_desc_endpoint_t const* p_csep = (midi_cs_desc_endpoint_t const*)p_mdh; | ||||
|       if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) | ||||
|       { | ||||
|       midi_cs_desc_endpoint_t const *p_csep = (midi_cs_desc_endpoint_t const *) p_mdh; | ||||
|       if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { | ||||
|         TU_VERIFY(p_midi_host->ep_out == prev_ep_addr); | ||||
|         TU_VERIFY(p_midi_host->num_cables_tx == 0); | ||||
|         p_midi_host->num_cables_tx = p_csep->bNumEmbMIDIJack; | ||||
| #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|   #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         uint8_t jack; | ||||
|         uint8_t max_jack = p_midi_host->num_cables_tx; | ||||
|         if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) | ||||
|         { | ||||
|             max_jack = sizeof(p_midi_host->ep_out_associated_jacks); | ||||
|         if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) { | ||||
|           max_jack = sizeof(p_midi_host->ep_out_associated_jacks); | ||||
|         } | ||||
|         for (jack = 0; jack < max_jack; jack++) | ||||
|         { | ||||
|         for (jack = 0; jack < max_jack; jack++) { | ||||
|           p_midi_host->ep_out_associated_jacks[jack] = p_csep->baAssocJackID[jack]; | ||||
|         } | ||||
| #endif | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|   #endif | ||||
|       } else { | ||||
|         TU_VERIFY(p_midi_host->ep_in == prev_ep_addr); | ||||
|         TU_VERIFY(p_midi_host->num_cables_rx == 0); | ||||
|         p_midi_host->num_cables_rx = p_csep->bNumEmbMIDIJack; | ||||
| #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|   #if CFG_MIDI_HOST_DEVSTRINGS | ||||
|         uint8_t jack; | ||||
|         uint8_t max_jack = p_midi_host->num_cables_rx; | ||||
|         if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) | ||||
|         { | ||||
|             max_jack = sizeof(p_midi_host->ep_in_associated_jacks); | ||||
|         if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) { | ||||
|           max_jack = sizeof(p_midi_host->ep_in_associated_jacks); | ||||
|         } | ||||
|         for (jack = 0; jack < max_jack; jack++) | ||||
|         { | ||||
|         for (jack = 0; jack < max_jack; jack++) { | ||||
|           p_midi_host->ep_in_associated_jacks[jack] = p_csep->baAssocJackID[jack]; | ||||
|         } | ||||
| #endif | ||||
|   #endif | ||||
|       } | ||||
|       len_parsed += p_csep->bLength; | ||||
|       prev_ep_addr = 0; | ||||
|     } | ||||
|     else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { | ||||
|     } else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { | ||||
|       // parse out the bulk endpoint info | ||||
|       tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *)p_mdh; | ||||
|       tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_mdh; | ||||
|       TU_LOG2("found ENDPOINT Descriptor for %u\r\n", p_ep->bEndpointAddress); | ||||
|       if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) | ||||
|       { | ||||
|       if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { | ||||
|         TU_VERIFY(p_midi_host->ep_out == 0); | ||||
|         TU_VERIFY(p_midi_host->num_cables_tx == 0); | ||||
|         p_midi_host->ep_out = p_ep->bEndpointAddress; | ||||
|         p_midi_host->ep_out_max = p_ep->wMaxPacketSize; | ||||
|         if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) | ||||
|         if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) { | ||||
|           p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE; | ||||
|         } | ||||
|         prev_ep_addr = p_midi_host->ep_out; | ||||
|         out_desc = p_ep; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|       } else { | ||||
|         TU_VERIFY(p_midi_host->ep_in == 0); | ||||
|         TU_VERIFY(p_midi_host->num_cables_rx == 0); | ||||
|         p_midi_host->ep_in = p_ep->bEndpointAddress; | ||||
|         p_midi_host->ep_in_max = p_ep->wMaxPacketSize; | ||||
|         if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) | ||||
|         if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) { | ||||
|           p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE; | ||||
|         } | ||||
|         prev_ep_addr = p_midi_host->ep_in; | ||||
|         in_desc = p_ep; | ||||
|       } | ||||
|       len_parsed += p_mdh->bLength; | ||||
|     } | ||||
|     p_desc = tu_desc_next(p_desc); | ||||
|     p_mdh = (midi_desc_header_t const *)p_desc; | ||||
|     p_mdh = (midi_desc_header_t const *) p_desc; | ||||
|   } | ||||
|   TU_VERIFY((p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) || | ||||
|             (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)); | ||||
|   TU_LOG1("MIDI descriptor parsed successfully\r\n"); | ||||
|   // remove duplicate string indices | ||||
|   for (int idx=0; idx < p_midi_host->num_string_indices; idx++) { | ||||
|       for (int jdx = idx+1; jdx < p_midi_host->num_string_indices; jdx++) { | ||||
|           while (jdx < p_midi_host->num_string_indices &&  p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { | ||||
|               // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 | ||||
|               p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices-1]; | ||||
|               --p_midi_host->num_string_indices; | ||||
|           } | ||||
|   for (int idx = 0; idx < p_midi_host->num_string_indices; idx++) { | ||||
|     for (int jdx = idx + 1; jdx < p_midi_host->num_string_indices; jdx++) { | ||||
|       while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { | ||||
|         // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 | ||||
|         p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices - 1]; | ||||
|         --p_midi_host->num_string_indices; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   if (in_desc) | ||||
|   { | ||||
|   if (in_desc) { | ||||
|     TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); | ||||
|     // Some devices always return exactly the request length so transfers won't complete | ||||
|     // unless you assume every transfer is the last one. | ||||
|     // TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true); | ||||
|   } | ||||
|   if (out_desc) | ||||
|   { | ||||
|   if (out_desc) { | ||||
|     TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); | ||||
|   } | ||||
|   p_midi_host->dev_addr = dev_addr; | ||||
|  | ||||
|   if (tuh_midi_mount_cb) | ||||
|   { | ||||
|   if (tuh_midi_mount_cb) { | ||||
|     tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); | ||||
|   } | ||||
|   return true; | ||||
| @@ -478,7 +456,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d | ||||
|  | ||||
| bool tuh_midi_configured(uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   return p_midi_host->configured; | ||||
| } | ||||
| @@ -486,7 +464,7 @@ bool tuh_midi_configured(uint8_t dev_addr) | ||||
| bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) | ||||
| { | ||||
|   (void) itf_num; | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   p_midi_host->configured = true; | ||||
|  | ||||
| @@ -498,43 +476,36 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) | ||||
| //--------------------------------------------------------------------+ | ||||
| // Stream API | ||||
| //--------------------------------------------------------------------+ | ||||
| static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) | ||||
| { | ||||
| static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) { | ||||
|   // No data to send | ||||
|   if ( !tu_fifo_count(&midi->tx_ff) ) return 0; | ||||
|   if ( !tu_fifo_count(&midi->tx_ff) ) { return 0; } | ||||
|  | ||||
|   // skip if previous transfer not complete | ||||
|   TU_VERIFY( usbh_edpt_claim(dev_addr, midi->ep_out) ); | ||||
|  | ||||
|   uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max); | ||||
|  | ||||
|   if (count) | ||||
|   { | ||||
|     TU_ASSERT( usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0 ); | ||||
|   if (count) { | ||||
|     TU_ASSERT(usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0); | ||||
|     return count; | ||||
|   }else | ||||
|   { | ||||
|   } else { | ||||
|     // Release endpoint since we don't make any transfer | ||||
|     usbh_edpt_release(dev_addr, midi->ep_out); | ||||
|     return 0; | ||||
|   } | ||||
| } | ||||
|  | ||||
| bool tuh_midi_read_poll( uint8_t dev_addr ) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
| bool tuh_midi_read_poll(uint8_t dev_addr) { | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   bool result = false; | ||||
|  | ||||
|   bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in); | ||||
|   if (in_edpt_not_busy) | ||||
|   { | ||||
|   if (in_edpt_not_busy) { | ||||
|     TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); | ||||
|     TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0); | ||||
|     result = true; | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|   } else { | ||||
|     // Maybe the IN endpoint is only busy because the RP2040 host hardware | ||||
|     // is retrying a NAK'd IN transfer forever. Try aborting the NAK'd | ||||
|     // transfer to allow other transfers to happen on the one shared | ||||
| @@ -546,7 +517,7 @@ bool tuh_midi_read_poll( uint8_t dev_addr ) | ||||
|  | ||||
| uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   TU_VERIFY(cable_num < p_midi_host->num_cables_tx); | ||||
|   midi_stream_t *stream = &p_midi_host->stream_write; | ||||
| @@ -673,7 +644,7 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con | ||||
|  | ||||
| bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|  | ||||
|   if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4) | ||||
| @@ -688,7 +659,7 @@ bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) | ||||
|  | ||||
| uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|  | ||||
|   uint32_t bytes_flushed = 0; | ||||
| @@ -703,7 +674,7 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) | ||||
| //--------------------------------------------------------------------+ | ||||
| uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   TU_VERIFY(p_midi_host->ep_out != 0); // returns 0 if fails | ||||
|   return p_midi_host->num_cables_tx; | ||||
| @@ -711,7 +682,7 @@ uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) | ||||
|  | ||||
| uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   TU_VERIFY(p_midi_host->ep_in != 0); // returns 0 if fails | ||||
|   return p_midi_host->num_cables_rx; | ||||
| @@ -719,7 +690,7 @@ uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) | ||||
|  | ||||
| bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4); | ||||
|   return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4; | ||||
| @@ -727,7 +698,7 @@ bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) | ||||
|  | ||||
| uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   uint32_t bytes_buffered = 0; | ||||
|   TU_ASSERT(p_cable_num); | ||||
| @@ -848,7 +819,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * | ||||
|  | ||||
| uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   uint8_t num_cables = 0; | ||||
|   if (p_midi_host) | ||||
| @@ -860,7 +831,7 @@ uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) | ||||
|  | ||||
| uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   uint8_t num_cables = 0; | ||||
|   if (p_midi_host) | ||||
| @@ -897,7 +868,7 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) | ||||
| uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) | ||||
| { | ||||
|   uint8_t nstrings = 0; | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   nstrings = p_midi_host->num_cables_rx; | ||||
|   if (nstrings > max_istrings) | ||||
| @@ -916,7 +887,7 @@ uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint | ||||
| uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) | ||||
| { | ||||
|   uint8_t nstrings = 0; | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   nstrings = p_midi_host->num_cables_tx; | ||||
|   if (nstrings > max_istrings) | ||||
| @@ -935,7 +906,7 @@ uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint | ||||
|  | ||||
| uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) | ||||
| { | ||||
|   midih_interface_t *p_midi_host = get_midi_host(dev_addr); | ||||
|   midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); | ||||
|   TU_VERIFY(p_midi_host != NULL); | ||||
|   uint8_t nstrings = p_midi_host->num_string_indices; | ||||
|   if (nstrings) | ||||
|   | ||||
| @@ -37,16 +37,25 @@ | ||||
| //--------------------------------------------------------------------+ | ||||
| // Class Driver Configuration | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // TODO Highspeed bulk transfer can be up to 512 bytes | ||||
| #ifndef CFG_TUH_HID_EPIN_BUFSIZE | ||||
| #define CFG_TUH_HID_EPIN_BUFSIZE 64 | ||||
| #ifndef CFG_TUH_MAX_CABLES | ||||
| #define CFG_TUH_MAX_CABLES 16 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUH_HID_EPOUT_BUFSIZE | ||||
| #define CFG_TUH_HID_EPOUT_BUFSIZE 64 | ||||
| #ifndef CFG_TUH_MIDI_RX_BUFSIZE | ||||
| #define CFG_TUH_MIDI_RX_BUFSIZE 64 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUH_MIDI_TX_BUFSIZE | ||||
| #define CFG_TUH_MIDI_TX_BUFSIZE 64 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUH_MIDI_EP_BUFSIZE | ||||
| #define CFG_TUH_MIDI_EP_BUFSIZE 64 | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_MIDI_HOST_DEVSTRINGS | ||||
| #define CFG_MIDI_HOST_DEVSTRINGS 0 | ||||
| #endif | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Application API (Single Interface) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach