diff --git a/firmware/usbstack/usb_audio.c b/firmware/usbstack/usb_audio.c index 9dc96579e7..fad3d12b8c 100644 --- a/firmware/usbstack/usb_audio.c +++ b/firmware/usbstack/usb_audio.c @@ -1204,14 +1204,13 @@ static bool usb_audio_control_request(struct usb_ctrlrequest* req, void *reqdata * connection is ready to be used. Currently just sets * the audio sample rate to default. */ -static void usb_audio_init_connection(void) +static int usb_audio_init_connection(void) { logf("usbaudio: init connection"); // make sure we can get the buffers first... - // TODO: disable this driver when failed if (usb_audio_request_buf()) - return; + return -1; usbaudio_active = true; dsp = dsp_get_config(CODEC_IDX_AUDIO); @@ -1227,6 +1226,7 @@ static void usb_audio_init_connection(void) set_playback_sampling_frequency(HW_SAMPR_DEFAULT); tmp_saved_vol = sound_current(SOUND_VOLUME); usb_audio_playing = false; + return 0; } /* diff --git a/firmware/usbstack/usb_class_driver.h b/firmware/usbstack/usb_class_driver.h index dc19c31ad5..5d63ce0b89 100644 --- a/firmware/usbstack/usb_class_driver.h +++ b/firmware/usbstack/usb_class_driver.h @@ -38,7 +38,14 @@ struct usb_class_driver_ep_allocation { struct usb_class_driver { /* First some runtime data */ + + /* there are three possible runtime states for class driver: + * !enabled -> disabled, invisible from host + * enabled && !error -> enabled, healthy + * enabled && error -> recognized by host, but failed */ bool enabled; + bool error; + int first_interface; int last_interface; @@ -69,8 +76,9 @@ struct usb_class_driver { /* Tells the driver that a usb connection has been set up and is now ready to use. + Returns 0 on success and -1 on error. Optional function */ - void (*init_connection)(void); + int (*init_connection)(void); /* Initialises the driver. This can be called multiple times, and should not perform any action that can disturb other threads diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 3f1dee129c..814d502242 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -236,7 +236,7 @@ static void usb_core_control_request_handler(struct usb_ctrlrequest* req, void* static unsigned char response_data[256] USB_DEVBSS_ATTR; -#define is_active(driver) ((driver)->enabled && (driver)->config == usb_config) +#define is_active(driver) ((driver)->enabled && !(driver)->error && (driver)->config == usb_config) #define has_if(driver, interface) ((interface) >= (driver)->first_interface && (interface) < (driver)->last_interface) /** NOTE Serial Number @@ -399,6 +399,7 @@ void usb_core_init(void) * yet which drivers will be enabled */ for(i = 0; i < USB_NUM_DRIVERS; i++) { drivers[i]->enabled = false; + drivers[i]->error = false; drivers[i]->first_interface = 0; drivers[i]->last_interface = 0; if(drivers[i]->init != NULL) { @@ -472,7 +473,7 @@ void usb_core_hotswap_event(int volume, bool inserted) { int i; for(i = 0; i < USB_NUM_DRIVERS; i++) - if(drivers[i]->enabled && drivers[i]->notify_hotswap != NULL) + if(is_active(drivers[i]) && drivers[i]->notify_hotswap != NULL) drivers[i]->notify_hotswap(volume, inserted); } #endif @@ -856,10 +857,14 @@ static int usb_core_do_set_config(uint8_t new_config) if(usb_config != 0) { init_deinit_endpoints(usb_config - 1, true); for(int i = 0; i < USB_NUM_DRIVERS; i++) { - if(is_active(drivers[i]) && drivers[i]->init_connection != NULL) { - drivers[i]->init_connection(); - require_exclusive |= drivers[i]->needs_exclusive_storage; + if(!is_active(drivers[i])) { + continue; } + if(drivers[i]->init_connection != NULL && drivers[i]->init_connection() < 0) { + drivers[i]->error = true; + continue; + } + require_exclusive |= drivers[i]->needs_exclusive_storage; } } diff --git a/firmware/usbstack/usb_hid.c b/firmware/usbstack/usb_hid.c index 3b231cfa8c..ac06691df4 100644 --- a/firmware/usbstack/usb_hid.c +++ b/firmware/usbstack/usb_hid.c @@ -543,11 +543,12 @@ static int usb_hid_get_config_descriptor(unsigned char *dest, int max_packet_siz return (int)(dest - orig_dest); } -static void usb_hid_init_connection(void) +static int usb_hid_init_connection(void) { logf("hid: init connection"); active = true; currently_sending = false; + return 0; } /* called by usb_core_init() */ diff --git a/firmware/usbstack/usb_iap.c b/firmware/usbstack/usb_iap.c index 99492f791b..2d6d3d3022 100644 --- a/firmware/usbstack/usb_iap.c +++ b/firmware/usbstack/usb_iap.c @@ -373,7 +373,7 @@ static int usb_iap_get_config_descriptor(unsigned char* dest, int max_packet_siz return dest - orig_dest; } -static void usb_iap_init_connection(void) { +static int usb_iap_init_connection(void) { stream.sample_rate = 48000; last_charge_state = -1; last_minute = -1; @@ -381,10 +381,8 @@ static void usb_iap_init_connection(void) { iap_debug_reset_timestamp(); - /* TODO: disable iap on error */ - /* init audio sink */ - check_act(iap_audio_init(), return); + check_act(iap_audio_init(), return -1); /* init libiap */ if(!iap_ctx_mutex_initialized) { @@ -416,11 +414,12 @@ static void usb_iap_init_connection(void) { iap_initialized = true; LOG("initialized"); - return; + return 0; cleanup_audio: _iap_release_ctx(); iap_audio_deinit(); + return -1; } static int usb_iap_set_interface(int intf, int alt) { diff --git a/firmware/usbstack/usb_serial.c b/firmware/usbstack/usb_serial.c index 80aaaaef5d..5490d1db11 100644 --- a/firmware/usbstack/usb_serial.c +++ b/firmware/usbstack/usb_serial.c @@ -329,7 +329,7 @@ static bool usb_serial_control_request(struct usb_ctrlrequest* req, void* reqdat return handled; } -static void usb_serial_init_connection(void) +static int usb_serial_init_connection(void) { /* prime rx endpoint */ usb_drv_recv_nonblocking(EP_OUT, receive_buffer, RECV_BUFFER_SIZE); @@ -341,6 +341,7 @@ static void usb_serial_init_connection(void) sendout(); } active=true; + return 0; } /* called by usb_code_init() */ diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index 17677c44cd..c4bdbf9841 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c @@ -436,7 +436,7 @@ static int usb_storage_get_config_descriptor(unsigned char *dest,int max_packet_ #else static int usb_handle = 0; #endif -static void usb_storage_init_connection(void) +static int usb_storage_init_connection(void) { logf("ums: set config"); /* prime rx endpoint. We only need room for commands */ @@ -483,6 +483,7 @@ static void usb_storage_init_connection(void) ejected[i] = !check_disk_present(IF_MD(i)); queue_broadcast(SYS_USB_LUN_LOCKED, (i<<16)+0); } + return 0; } void usb_storage_disconnect(void)