Shuffle cores.
This commit is contained in:
		
							parent
							
								
									4d224f5e21
								
							
						
					
					
						commit
						062ca82e10
					
				| 
						 | 
					@ -170,17 +170,18 @@ void apply_filter_configuration(filter_configuration_tlv *filters) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type_changed) {
 | 
					    if (type_changed) {
 | 
				
			||||||
        fix16_t left[2] = { bqf_filters_mem_left[0].x_2, bqf_filters_mem_left[0].x_1 };
 | 
					 | 
				
			||||||
        fix16_t right[2] = { bqf_filters_mem_right[0].x_2, bqf_filters_mem_right[0].x_1 };
 | 
					 | 
				
			||||||
        for (int i=0; i<MAX_FILTER_STAGES; i++) {
 | 
					 | 
				
			||||||
            bqf_memreset(&bqf_filters_mem_left[i]);
 | 
					 | 
				
			||||||
            bqf_memreset(&bqf_filters_mem_right[i]);
 | 
					 | 
				
			||||||
        // The memory structure stores the last 2 input samples, we can replay them into
 | 
					        // The memory structure stores the last 2 input samples, we can replay them into
 | 
				
			||||||
        // the new filter rather than starting again from scratch.
 | 
					        // the new filter rather than starting again from scratch.
 | 
				
			||||||
 | 
					        fix16_t left[2] = { bqf_filters_mem_left[0].x_2, bqf_filters_mem_left[0].x_1 };
 | 
				
			||||||
 | 
					        fix16_t right[2] = { bqf_filters_mem_right[0].x_2, bqf_filters_mem_right[0].x_1 };
 | 
				
			||||||
 | 
					        for (int i=0; i<filter_stages; i++) {
 | 
				
			||||||
 | 
					            bqf_memreset(&bqf_filters_mem_left[i]);
 | 
				
			||||||
 | 
					            bqf_memreset(&bqf_filters_mem_right[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            left[0] = bqf_transform(left[0], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
					            left[0] = bqf_transform(left[0], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
				
			||||||
            left[1] = bqf_transform(left[1], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
					            left[1] = bqf_transform(left[1], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
				
			||||||
            right[0] = bqf_transform(right[0], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
					            right[0] = bqf_transform(right[0], &bqf_filters_right[i], &bqf_filters_mem_right[i]);
 | 
				
			||||||
            right[1] = bqf_transform(right[1], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
 | 
					            right[1] = bqf_transform(right[1], &bqf_filters_right[i], &bqf_filters_mem_right[i]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -444,6 +445,17 @@ void config_out_packet(struct usb_endpoint *ep) {
 | 
				
			||||||
    struct usb_buffer *buffer = usb_current_out_packet_buffer(ep);
 | 
					    struct usb_buffer *buffer = usb_current_out_packet_buffer(ep);
 | 
				
			||||||
    //printf("config_out_packet %d\n", buffer->data_len);
 | 
					    //printf("config_out_packet %d\n", buffer->data_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (write_offset + buffer->data_len > CFG_BUFFER_SIZE)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Dont actually write, but this will prevent us for attempting to process this command if a zero byte packet arrives later.
 | 
				
			||||||
 | 
					        write_offset += buffer->data_len;
 | 
				
			||||||
 | 
					        printf("Error! Overflow receive buffer [write_offset=%d]\n", write_offset);
 | 
				
			||||||
 | 
					        tlv_header* result = ((tlv_header*) result_buffer);
 | 
				
			||||||
 | 
					        result->type = NOK;
 | 
				
			||||||
 | 
					        result->length = 4;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        memcpy(&working_configuration[inactive_working_configuration][write_offset], buffer->data, buffer->data_len);
 | 
					        memcpy(&working_configuration[inactive_working_configuration][write_offset], buffer->data, buffer->data_len);
 | 
				
			||||||
        write_offset += buffer->data_len;
 | 
					        write_offset += buffer->data_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -454,7 +466,7 @@ void config_out_packet(struct usb_endpoint *ep) {
 | 
				
			||||||
            process_cmd((tlv_header*) working_configuration[inactive_working_configuration]);
 | 
					            process_cmd((tlv_header*) working_configuration[inactive_working_configuration]);
 | 
				
			||||||
            read_offset = 0;
 | 
					            read_offset = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    usb_grow_transfer(ep->current_transfer, 1);
 | 
					    usb_grow_transfer(ep->current_transfer, 1);
 | 
				
			||||||
    usb_packet_done(ep);
 | 
					    usb_packet_done(ep);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -479,6 +491,7 @@ void config_in_packet(struct usb_endpoint *ep) {
 | 
				
			||||||
    if (read_offset >= transfer_length) {
 | 
					    if (read_offset >= transfer_length) {
 | 
				
			||||||
        // Done
 | 
					        // Done
 | 
				
			||||||
        read_offset = 0;
 | 
					        read_offset = 0;
 | 
				
			||||||
 | 
					        write_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If the client reads again, return nothing
 | 
					        // If the client reads again, return nothing
 | 
				
			||||||
        result->type = NOK;
 | 
					        result->type = NOK;
 | 
				
			||||||
| 
						 | 
					@ -489,13 +502,32 @@ void config_in_packet(struct usb_endpoint *ep) {
 | 
				
			||||||
    usb_packet_done(ep);
 | 
					    usb_packet_done(ep);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void configuration_ep_on_stall_change(struct usb_endpoint *ep) {
 | 
				
			||||||
 | 
					    printf("Config EP stall change: %d\n", usb_is_endpoint_stalled(ep));
 | 
				
			||||||
 | 
					    if (!usb_is_endpoint_stalled(ep)) {
 | 
				
			||||||
 | 
					        write_offset = 0;
 | 
				
			||||||
 | 
					        tlv_header* request = ((tlv_header*) working_configuration[inactive_working_configuration]);
 | 
				
			||||||
 | 
					        request->type = NOK;
 | 
				
			||||||
 | 
					        request->length = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void configuration_ep_on_cancel(struct usb_endpoint *ep) {
 | 
				
			||||||
 | 
					    printf("Config EP on cancel\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    write_offset = 0;
 | 
				
			||||||
 | 
					    tlv_header* request = ((tlv_header*) working_configuration[inactive_working_configuration]);
 | 
				
			||||||
 | 
					    request->type = NOK;
 | 
				
			||||||
 | 
					    request->length = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void apply_core1_config() {
 | 
					void apply_core1_config() {
 | 
				
			||||||
    if (reload_config) {
 | 
					    if (reload_config) {
 | 
				
			||||||
        uint32_t ints = save_and_disable_interrupts();
 | 
					        //uint32_t ints = save_and_disable_interrupts();
 | 
				
			||||||
        reload_config = false;
 | 
					        reload_config = false;
 | 
				
			||||||
        const uint8_t active_configuration = inactive_working_configuration ? 0 : 1;
 | 
					        const uint8_t active_configuration = inactive_working_configuration ? 0 : 1;
 | 
				
			||||||
        apply_configuration((tlv_header*) working_configuration[active_configuration]);
 | 
					        apply_configuration((tlv_header*) working_configuration[active_configuration]);
 | 
				
			||||||
        restore_interrupts(ints);
 | 
					        //restore_interrupts(ints);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ struct usb_endpoint;
 | 
				
			||||||
#define INIT_FILTER2(T) { \
 | 
					#define INIT_FILTER2(T) { \
 | 
				
			||||||
    filter2 *args = (filter2 *)ptr; \
 | 
					    filter2 *args = (filter2 *)ptr; \
 | 
				
			||||||
    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->Q, &bqf_filters_left[filter_stages]); \
 | 
					    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->Q, &bqf_filters_left[filter_stages]); \
 | 
				
			||||||
    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->Q, &bqf_filters_right[filter_stages]); \
 | 
					    memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t)); \
 | 
				
			||||||
    ptr += sizeof(filter2); \
 | 
					    ptr += sizeof(filter2); \
 | 
				
			||||||
    break; \
 | 
					    break; \
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -33,13 +33,15 @@ struct usb_endpoint;
 | 
				
			||||||
#define INIT_FILTER3(T) { \
 | 
					#define INIT_FILTER3(T) { \
 | 
				
			||||||
    filter3 *args = (filter3 *)ptr; \
 | 
					    filter3 *args = (filter3 *)ptr; \
 | 
				
			||||||
    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->db_gain, args->Q, &bqf_filters_left[filter_stages]); \
 | 
					    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->db_gain, args->Q, &bqf_filters_left[filter_stages]); \
 | 
				
			||||||
    bqf_##T##_config(SAMPLING_FREQ, args->f0, args->db_gain, args->Q, &bqf_filters_right[filter_stages]); \
 | 
					    memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t)); \
 | 
				
			||||||
    ptr += sizeof(filter3); \
 | 
					    ptr += sizeof(filter3); \
 | 
				
			||||||
    break; \
 | 
					    break; \
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void config_in_packet(struct usb_endpoint *ep);
 | 
					void config_in_packet(struct usb_endpoint *ep);
 | 
				
			||||||
void config_out_packet(struct usb_endpoint *ep);
 | 
					void config_out_packet(struct usb_endpoint *ep);
 | 
				
			||||||
 | 
					void configuration_ep_on_stall_change(struct usb_endpoint *ep);
 | 
				
			||||||
 | 
					void configuration_ep_on_cancel(struct usb_endpoint *ep);
 | 
				
			||||||
extern void load_config();
 | 
					extern void load_config();
 | 
				
			||||||
extern void apply_core1_config();
 | 
					extern void apply_core1_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,54 +88,6 @@ int main(void) {
 | 
				
			||||||
        __wfi();
 | 
					        __wfi();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Here's the meat. It's where the data buffer from USB gets transformed from
 | 
					 | 
				
			||||||
// PCM data into I2S data that gets shipped out to the PCM3060. It really
 | 
					 | 
				
			||||||
// belongs with the other USB-related code due to its utter indecipherability,
 | 
					 | 
				
			||||||
// but it's placed here to emphasize its importance.
 | 
					 | 
				
			||||||
static void _as_audio_packet(struct usb_endpoint *ep) {
 | 
					 | 
				
			||||||
    struct usb_buffer *usb_buffer = usb_current_out_packet_buffer(ep);
 | 
					 | 
				
			||||||
    int16_t *in = (int16_t *) usb_buffer->data;
 | 
					 | 
				
			||||||
    int32_t *out = (int32_t *) userbuf;
 | 
					 | 
				
			||||||
    int samples = usb_buffer->data_len / 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (preprocessing.reverse_stereo) {
 | 
					 | 
				
			||||||
        for (int i = 0; i < samples; i+=2) {
 | 
					 | 
				
			||||||
            out[i] = in[i+1];
 | 
					 | 
				
			||||||
            out[i+1] = in[i];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        for (int i = 0; i < samples; i++)
 | 
					 | 
				
			||||||
            out[i] = in[i];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    multicore_fifo_push_blocking(CORE0_READY);
 | 
					 | 
				
			||||||
    multicore_fifo_push_blocking(samples);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (int j = 0; j < filter_stages; j++) {
 | 
					 | 
				
			||||||
        // Left channel filter
 | 
					 | 
				
			||||||
        for (int i = 0; i < samples; i += 2) {
 | 
					 | 
				
			||||||
            fix16_t x_f16 = fix16_mul(fix16_from_int((int16_t) out[i]), preprocessing.preamp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            x_f16 = bqf_transform(x_f16, &bqf_filters_left[j],
 | 
					 | 
				
			||||||
                &bqf_filters_mem_left[j]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            out[i] = (int32_t) fix16_to_int(x_f16);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Block until core 1 has finished transforming the data
 | 
					 | 
				
			||||||
    uint32_t ready = multicore_fifo_pop_blocking();
 | 
					 | 
				
			||||||
    multicore_fifo_push_blocking(CORE0_READY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    i2s_stream_write(&i2s_write_obj, userbuf, samples * 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // keep on truckin'
 | 
					 | 
				
			||||||
    usb_grow_transfer(ep->current_transfer, 1);
 | 
					 | 
				
			||||||
    usb_packet_done(ep);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void update_volume()
 | 
					static void update_volume()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (audio_state._volume != audio_state._target_volume) {
 | 
					    if (audio_state._volume != audio_state._target_volume) {
 | 
				
			||||||
| 
						 | 
					@ -162,22 +114,84 @@ static void update_volume()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Here's the meat. It's where the data buffer from USB gets transformed from
 | 
				
			||||||
 | 
					// PCM data into I2S data that gets shipped out to the PCM3060. It really
 | 
				
			||||||
 | 
					// belongs with the other USB-related code due to its utter indecipherability,
 | 
				
			||||||
 | 
					// but it's placed here to emphasize its importance.
 | 
				
			||||||
 | 
					static void _as_audio_packet(struct usb_endpoint *ep) {
 | 
				
			||||||
 | 
					    struct usb_buffer *usb_buffer = usb_current_out_packet_buffer(ep);
 | 
				
			||||||
 | 
					    int16_t *in = (int16_t *) usb_buffer->data;
 | 
				
			||||||
 | 
					    int32_t *out = (int32_t *) userbuf;
 | 
				
			||||||
 | 
					    int samples = usb_buffer->data_len / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (preprocessing.reverse_stereo) {
 | 
				
			||||||
 | 
					        for (int i = 0; i < samples; i+=2) {
 | 
				
			||||||
 | 
					            out[i] = in[i+1];
 | 
				
			||||||
 | 
					            out[i+1] = in[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        for (int i = 0; i < samples; i++)
 | 
				
			||||||
 | 
					            out[i] = in[i];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    // Make sure core 1 is ready for us.
 | 
				
			||||||
 | 
					    multicore_fifo_pop_blocking();
 | 
				
			||||||
 | 
					    multicore_fifo_push_blocking(CORE0_READY);
 | 
				
			||||||
 | 
					    multicore_fifo_push_blocking(samples);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int j = 0; j < filter_stages; j++) {
 | 
				
			||||||
 | 
					        // Left channel filter
 | 
				
			||||||
 | 
					        for (int i = 0; i < samples; i += 2) {
 | 
				
			||||||
 | 
					            fix16_t x_f16 = fix16_mul(fix16_from_int((int16_t) out[i]), preprocessing.preamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            x_f16 = bqf_transform(x_f16, &bqf_filters_left[j],
 | 
				
			||||||
 | 
					                &bqf_filters_mem_left[j]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out[i] = (int32_t) fix16_to_int(x_f16);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Block until core 1 has finished transforming the data
 | 
				
			||||||
 | 
					    uint32_t ready = multicore_fifo_pop_blocking();
 | 
				
			||||||
 | 
					    multicore_fifo_push_blocking(CORE0_READY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Update the volume if required. We do this from core1 as
 | 
				
			||||||
 | 
					    // core0 is more heavily loaded, doing this from core0 can
 | 
				
			||||||
 | 
					    // lead to audio crackling.
 | 
				
			||||||
 | 
					    update_volume();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Update filters if required
 | 
				
			||||||
 | 
					    apply_core1_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Wait for core 1 to finish
 | 
				
			||||||
 | 
					    //multicore_fifo_pop_blocking();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // keep on truckin'
 | 
				
			||||||
 | 
					    usb_grow_transfer(ep->current_transfer, 1);
 | 
				
			||||||
 | 
					    usb_packet_done(ep);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void core1_entry() {
 | 
					void core1_entry() {
 | 
				
			||||||
    uint8_t *userbuf = (uint8_t *) multicore_fifo_pop_blocking();
 | 
					    uint8_t *userbuf = (uint8_t *) multicore_fifo_pop_blocking();
 | 
				
			||||||
    int32_t *out = (int32_t *) userbuf;
 | 
					    int32_t *out = (int32_t *) userbuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Signal that the thread has started
 | 
				
			||||||
    multicore_fifo_push_blocking(CORE1_READY);
 | 
					    multicore_fifo_push_blocking(CORE1_READY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        // Signal to core 0 that we are ready to accept new data
 | 
				
			||||||
 | 
					        multicore_fifo_push_blocking(CORE1_READY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Block until the userbuf is filled with data
 | 
					        // Block until the userbuf is filled with data
 | 
				
			||||||
        uint32_t ready = multicore_fifo_pop_blocking();
 | 
					        uint32_t ready = multicore_fifo_pop_blocking();
 | 
				
			||||||
        while (ready != CORE0_READY)
 | 
					        while (ready != CORE0_READY)
 | 
				
			||||||
            ready = multicore_fifo_pop_blocking();
 | 
					            ready = multicore_fifo_pop_blocking();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        uint32_t limit = multicore_fifo_pop_blocking();
 | 
					        const uint32_t samples = multicore_fifo_pop_blocking();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int j = 0; j < filter_stages; j++) {
 | 
					        for (int j = 0; j < filter_stages; j++) {
 | 
				
			||||||
            for (int i = 1; i < limit; i += 2) {
 | 
					            for (int i = 1; i < samples; i += 2) {
 | 
				
			||||||
                fix16_t x_f16 = fix16_mul(fix16_from_int((int16_t) out[i]), preprocessing.preamp);
 | 
					                fix16_t x_f16 = fix16_mul(fix16_from_int((int16_t) out[i]), preprocessing.preamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                x_f16 = bqf_transform(x_f16, &bqf_filters_right[j],
 | 
					                x_f16 = bqf_transform(x_f16, &bqf_filters_right[j],
 | 
				
			||||||
| 
						 | 
					@ -193,13 +207,7 @@ void core1_entry() {
 | 
				
			||||||
        // Wait for Core 0 to finish running its filtering before we apply config updates
 | 
					        // Wait for Core 0 to finish running its filtering before we apply config updates
 | 
				
			||||||
        multicore_fifo_pop_blocking();
 | 
					        multicore_fifo_pop_blocking();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Update filters if required
 | 
					        i2s_stream_write(&i2s_write_obj, userbuf, samples * 4);
 | 
				
			||||||
        apply_core1_config();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Update the volume if required. We do this from core1 as
 | 
					 | 
				
			||||||
        // core0 is more heavily loaded, doing this from core0 can
 | 
					 | 
				
			||||||
        // lead to audio crackling.
 | 
					 | 
				
			||||||
        update_volume();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -587,6 +595,7 @@ static const struct usb_transfer_type config_in_transfer_type = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct usb_transfer_type config_out_transfer_type = {
 | 
					static const struct usb_transfer_type config_out_transfer_type = {
 | 
				
			||||||
    .on_packet = config_out_packet,
 | 
					    .on_packet = config_out_packet,
 | 
				
			||||||
 | 
					    .on_cancel = configuration_ep_on_cancel,
 | 
				
			||||||
    .initial_packet_count = 1,
 | 
					    .initial_packet_count = 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -923,6 +932,7 @@ void usb_sound_card_init() {
 | 
				
			||||||
    config_in_transfer.type = &config_in_transfer_type;
 | 
					    config_in_transfer.type = &config_in_transfer_type;
 | 
				
			||||||
    usb_set_default_transfer(&ep_configuration_in, &config_in_transfer);
 | 
					    usb_set_default_transfer(&ep_configuration_in, &config_in_transfer);
 | 
				
			||||||
    config_out_transfer.type = &config_out_transfer_type;
 | 
					    config_out_transfer.type = &config_out_transfer_type;
 | 
				
			||||||
 | 
					    ep_configuration_out.on_stall_change = configuration_ep_on_stall_change;
 | 
				
			||||||
    usb_set_default_transfer(&ep_configuration_out, &config_out_transfer);
 | 
					    usb_set_default_transfer(&ep_configuration_out, &config_out_transfer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static struct usb_interface *const boot_device_interfaces[] = {
 | 
					    static struct usb_interface *const boot_device_interfaces[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue