static void at_sim_read_info(struct ofono_sim *sim, int fileid, const unsigned char *path, unsigned int path_len, ofono_sim_file_info_cb_t cb, void *data) { struct sim_data *sd = ofono_sim_get_data(sim); struct cb_data *cbd; char buf[128]; unsigned int len; if (sd->vendor == OFONO_VENDOR_OPTION_HSO) { unsigned char access[3] = { 0x00, 0x00, 0x00 }; if (fileid == SIM_EFAD_FILEID) { CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access, EF_STATUS_VALID, data); return; } } cbd = cb_data_new(cb, data); len = snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid); switch (sd->vendor) { default: if (path_len == 0) break; /* Fall through */ case OFONO_VENDOR_ZTE: case OFONO_VENDOR_HUAWEI: case OFONO_VENDOR_SIERRA: case OFONO_VENDOR_SPEEDUP: case OFONO_VENDOR_QUALCOMM_MSM: /* Maximum possible length */ len += sprintf(buf + len, ",0,0,255"); break; } if (path_len > 0) { len += sprintf(buf + len, ",,\""); for (; path_len; path_len--) len += sprintf(buf + len, "%02hhX", *path++); buf[len++] = '\"'; buf[len] = '\0'; } if (g_at_chat_send(sd->chat, buf, crsm_prefix, at_crsm_info_cb, cbd, g_free) > 0) return; g_free(cbd); CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, data); }
void ril_query_fast_dormancy(struct ofono_radio_settings *rs, ofono_radio_settings_fast_dormancy_query_cb_t cb, void *data) { struct radio_data *rd = ofono_radio_settings_get_data(rs); CALLBACK_WITH_SUCCESS(cb, rd->fast_dormancy, data); }
static void dun_gprs_attached_status(struct ofono_gprs *gprs, ofono_gprs_status_cb_t cb, void *data) { DBG(""); CALLBACK_WITH_SUCCESS(cb, 1, data); }
static void ril_query_passwd_state_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_sim *sim = cbd->user; struct sim_data *sd = ofono_sim_get_data(sim); ofono_sim_passwd_cb_t cb = cbd->cb; void *data = cbd->data; struct sim_app *apps[MAX_UICC_APPS]; struct sim_status status; guint i = 0; guint search_index = -1; gint state = ofono_sim_get_state(sim); if (ril_util_parse_sim_status(sd->ril, message, &status, apps) && status.num_apps) { DBG("num_apps: %d gsm_umts_index: %d", status.num_apps, status.gsm_umts_index); /* TODO(CDMA): need some kind of logic to * set the correct app_index, */ search_index = status.gsm_umts_index; for (i = 0; i < status.num_apps; i++) { if (i == search_index && apps[i]->app_type != RIL_APPTYPE_UNKNOWN) { current_active_app = apps[i]->app_type; configure_active_app(sd, apps[i], i); set_pin_lock_state(sim, apps[i]); break; } } ril_util_free_sim_apps(apps, status.num_apps); } DBG("passwd_state %u", sd->passwd_state); /* * To prevent double call to sim_initialize_after_pin from * sim_pin_query_cb we must prevent calling sim_pin_query_cb * when !OFONO_SIM_STATE_READY && OFONO_SIM_PASSWORD_NONE */ if ((state == OFONO_SIM_STATE_READY) || (sd->initialized == FALSE) || (sd->passwd_state != OFONO_SIM_PASSWORD_NONE)){ if (sd->passwd_state == OFONO_SIM_PASSWORD_NONE) sd->initialized = TRUE; if (state == OFONO_SIM_STATE_LOCKED_OUT) sd->initialized = FALSE; if (sd->passwd_state == OFONO_SIM_PASSWORD_INVALID) CALLBACK_WITH_FAILURE(cb, -1, data); else CALLBACK_WITH_SUCCESS(cb, sd->passwd_state, data); } }
static void sca_sim_query_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data; struct ofono_sms *sms = cbd->user; struct sms_data *sd = ofono_sms_get_data(sms); ofono_sms_sca_query_cb_t cb = cbd->cb; struct ofono_phone_number sca; struct sms_params *info; size_t len = sizeof(struct sms_params); uint8_t bcd_len; if (!check_sim(msg, SIM_SMS_RESP, READ_PARAMETER)) goto error; if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &info, len)) goto error; if (info->alphalen > 17) info->alphalen = 17; else if (info->alphalen < 1) info->alphalen = 1; info->alpha[info->alphalen - 1] = '\0'; sd->params.absent = info->absent; sd->params.tp_pid = info->tp_pid; sd->params.tp_dcs = info->tp_dcs; sd->params.tp_vp = info->tp_vp; memcpy(sd->params.dst, info->dst, sizeof(sd->params.dst)); memcpy(sd->params.sca, info->sca, sizeof(sd->params.sca)); sd->params.alphalen = info->alphalen; memcpy(sd->params.alpha, info->alpha, sizeof(sd->params.alpha)); /* * Bitmask indicating absence of parameters -- * If second bit is set it indicates that the SCA is absent */ if (info->absent & 0x2) goto error; bcd_len = info->sca[0]; if (bcd_len == 0 || bcd_len > 12) goto error; extract_bcd_number(info->sca + 2, bcd_len - 1, sca.number); sca.type = 0x80 | info->sca[1]; CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data); return; error: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); }
static void qmi_query_pin_retries(struct ofono_sim *sim, ofono_sim_pin_retries_cb_t cb, void *user_data) { struct sim_data *data = ofono_sim_get_data(sim); DBG(""); CALLBACK_WITH_SUCCESS(cb, data->retries, user_data); }
static void qmi_current_operator(struct ofono_netreg *netreg, ofono_netreg_operator_cb_t cb, void *user_data) { struct netreg_data *data = ofono_netreg_get_data(netreg); DBG(""); CALLBACK_WITH_SUCCESS(cb, &data->operator, user_data); }
static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data) { DBG(""); struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; struct parcel rilp, rilp_out; int mode = OFONO_RADIO_ACCESS_MODE_ANY; int pref; struct radio_data *rd = NULL; if (message->error == RIL_E_SUCCESS) { ril_util_init_parcel(message, &rilp); /*first item in int[] is len so let's skip that*/ parcel_r_int32(&rilp); pref = parcel_r_int32(&rilp); switch (pref) { case PREF_NET_TYPE_LTE_ONLY: mode = OFONO_RADIO_ACCESS_MODE_LTE; case PREF_NET_TYPE_GSM_ONLY: mode = OFONO_RADIO_ACCESS_MODE_GSM; break; case PREF_NET_TYPE_WCDMA: case PREF_NET_TYPE_GSM_WCDMA: /* according to UI design */ case PREF_NET_TYPE_GSM_WCDMA_AUTO:/* according to UI design */ mode = OFONO_RADIO_ACCESS_MODE_UMTS; break; case PREF_NET_TYPE_LTE_CDMA_EVDO: case PREF_NET_TYPE_LTE_GSM_WCDMA: case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA: if (!cb) { rd = cbd->user; parcel_init(&rilp_out); parcel_w_int32(&rilp_out, 1); parcel_w_int32(&rilp_out, rd->ratmode); g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, rilp_out.data, rilp_out.size, NULL, NULL, g_free); parcel_free(&rilp_out); } break; case PREF_NET_TYPE_CDMA_EVDO_AUTO: case PREF_NET_TYPE_CDMA_ONLY: case PREF_NET_TYPE_EVDO_ONLY: case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO: default: break; } if (cb) CALLBACK_WITH_SUCCESS(cb, mode, cbd->data); } else { if (cb) CALLBACK_WITH_FAILURE(cb, -1, cbd->data); } }
static void ril_csca_set_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sms_sca_set_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) CALLBACK_WITH_SUCCESS(cb, cbd->data); else CALLBACK_WITH_FAILURE(cb, cbd->data); }
static void bearer_set_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data; ofono_sms_bearer_set_cb_t cb = cbd->cb; if (check_sms(msg, SMS_SETTINGS_UPDATE_RESP, SMS_OK)) CALLBACK_WITH_SUCCESS(cb, cbd->data); else CALLBACK_WITH_FAILURE(cb, cbd->data); }
static gboolean request_success(gpointer data) { struct cb_data *cbd = data; ofono_ussd_cb_t cb = cbd->cb; CALLBACK_WITH_SUCCESS(cb, cbd->data); g_free(cbd); return FALSE; }
static void bt_disconnect(struct dundee_device *device, dundee_device_disconnect_cb_t cb, void *data) { struct bluetooth_device *bt = dundee_device_get_data(device); DBG("%p", bt); shutdown(bt->fd, SHUT_RDWR); CALLBACK_WITH_SUCCESS(cb, data); }
static void ril_set_online_cb(struct ril_msg *message, gpointer user_data) { DBG(""); struct cb_data *cbd = user_data; ofono_modem_online_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) CALLBACK_WITH_SUCCESS(cb, cbd->data); else CALLBACK_WITH_FAILURE(cb, cbd->data); }
static void u8500_info_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data; ofono_devinfo_query_cb_t cb = cbd->cb; GIsiSubBlockIter iter; uint8_t msgid; uint8_t status; msgid = g_isi_msg_id(msg); if (msgid != INFO_SERIAL_NUMBER_READ_RESP) goto error; if (g_isi_msg_error(msg) < 0) goto error; if (!g_isi_msg_data_get_byte(msg, 0, &status)) goto error; if (status != INFO_OK) goto error; for (g_isi_sb_iter_init(&iter, msg, 2); g_isi_sb_iter_is_valid(&iter); g_isi_sb_iter_next(&iter)) { uint8_t id = g_isi_sb_iter_get_id(&iter); uint8_t chars; char *info = NULL; if (id != INFO_SB_PRODUCT_INFO_MANUFACTURER && id != INFO_SB_PRODUCT_INFO_NAME && id != INFO_SB_MCUSW_VERSION && id != INFO_SB_SN_IMEI_PLAIN && id != INFO_SB_MODEMSW_VERSION) continue; if (g_isi_sb_iter_get_len(&iter) < 5) goto error; if (!g_isi_sb_iter_get_byte(&iter, &chars, 3)) goto error; if (!g_isi_sb_iter_get_latin_tag(&iter, &info, chars, 4)) goto error; CALLBACK_WITH_SUCCESS(cb, info, cbd->data); g_free(info); return; } error: CALLBACK_WITH_FAILURE(cb, "", cbd->data); }
static void ril_query_passwd_state(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb, void *data) { struct sim_data *sd = ofono_sim_get_data(sim); DBG("passwd_state %u", sd->passwd_state); if (sd->passwd_state == OFONO_SIM_PASSWORD_INVALID) CALLBACK_WITH_FAILURE(cb, -1, data); else CALLBACK_WITH_SUCCESS(cb, sd->passwd_state, data); }
static void ril_clear_topics(struct ofono_cbs *cbs, ofono_cbs_set_cb_t cb, void *user_data) { /* * Although this does not do anything real * towards network or modem, it is needed * because without it ofono core does not * change powered flag and it would allow * incoming cb messages. */ CALLBACK_WITH_SUCCESS(cb, user_data); }
static void ril_set_forward_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_call_forwarding_set_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) CALLBACK_WITH_SUCCESS(cb, cbd->data); else { ofono_error("CF setting failed"); CALLBACK_WITH_FAILURE(cb, cbd->data); } }
static void get_pin_status_cb(struct qmi_result *result, void *user_data) { struct cb_data *cbd = user_data; ofono_sim_passwd_cb_t cb = cbd->cb; struct sim_data *data = cbd->user; const struct qmi_dms_pin_status *pin; uint16_t len; int pin_type; DBG(""); if (qmi_result_set_error(result, NULL)) { CALLBACK_WITH_FAILURE(cb, -1, cbd->data); return; } pin = qmi_result_get(result, QMI_DMS_RESULT_PIN1_STATUS, &len); if (!pin) { CALLBACK_WITH_FAILURE(cb, -1, cbd->data); return; } DBG("PIN 1 status %d", pin->status); switch (pin->status) { case QMI_DMS_PIN_ENABLED_UNVERIFIED: pin_type = OFONO_SIM_PASSWORD_SIM_PIN; break; case QMI_DMS_PIN_ENABLED_VERIFIED: case QMI_DMS_PIN_DISABLED: pin_type = OFONO_SIM_PASSWORD_NONE; break; default: pin_type = OFONO_SIM_PASSWORD_INVALID; break; } data->retries[OFONO_SIM_PASSWORD_SIM_PIN] = pin->verify_retries; data->retries[OFONO_SIM_PASSWORD_SIM_PUK] = pin->unblock_retries; pin = qmi_result_get(result, QMI_DMS_RESULT_PIN2_STATUS, &len); if (!pin) goto done; DBG("PIN 2 status %d", pin->status); data->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = pin->verify_retries; data->retries[OFONO_SIM_PASSWORD_SIM_PUK2] = pin->unblock_retries; done: CALLBACK_WITH_SUCCESS(cb, pin_type, cbd->data); }
static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) CALLBACK_WITH_SUCCESS(cb, cbd->data); else { ofono_error("rat mode setting failed"); CALLBACK_WITH_FAILURE(cb, cbd->data); } }
static void sca_sim_set_resp_cb(const GIsiMessage *msg, void *data) { struct isi_cb_data *cbd = data; ofono_sms_sca_set_cb_t cb = cbd->cb; if (!check_sim(msg, SIM_SMS_RESP, UPDATE_PARAMETER)) { CALLBACK_WITH_FAILURE(cb, cbd->data); return; } CALLBACK_WITH_SUCCESS(cb, cbd->data); }
static void inf_pin_retries_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sim_pin_retries_cb_t cb = cbd->cb; struct sim_data *sd = cbd->user; struct parcel rilp; int32_t *data; int len; char *hex_dump; int expected; DBG(""); if (message->error != RIL_E_SUCCESS) { ofono_error("Reply failure: %s", ril_error_to_string(message->error)); goto error; } g_ril_init_parcel(message, &rilp); data = parcel_r_raw(&rilp, &len); if (data == NULL) { ofono_error("%s: malformed parcel", __func__); goto error; } hex_dump = encode_hex((unsigned char *) data, len, '\0'); g_ril_append_print_buf(sd->ril, "{%d,%s}", len, hex_dump); g_ril_print_response(sd->ril, message); g_free(hex_dump); expected = sizeof(int32_t) * 5; if (len < expected) { ofono_error("%s: reply too small", __func__); g_free(data); goto error; } /* First integer is INF_RIL_REQUEST_OEM_GET_REMAIN_SIM_PIN_ATTEMPTS */ sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] = data[1]; sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = data[2]; sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] = data[3]; sd->retries[OFONO_SIM_PASSWORD_SIM_PUK2] = data[4]; g_free(data); CALLBACK_WITH_SUCCESS(cb, sd->retries, cbd->data); return; error: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); }
/* Returns file info */ static gboolean fake_file_info(gpointer user) { struct isi_cb_data *cbd = user; ofono_sim_file_info_cb_t cb = cbd->cb; struct file_info const *fi = cbd->user; DBG("Returning static file_info for %04x", fi->fileid); CALLBACK_WITH_SUCCESS(cb, fi->length, fi->structure, fi->record_length, fi->access, cbd->data); g_free(cbd); return FALSE; }
gboolean ril_gprs_set_attached_cb(gpointer user_data) { struct cb_data *cbd = user_data; ofono_gprs_cb_t cb = cbd->cb; DBG(""); CALLBACK_WITH_SUCCESS(cb, cbd->data); g_free(cbd); /* Run once per g_idle_add() call */ return FALSE; }
static void ril_ussd_cancel_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_ussd *ussd = cbd->user; struct ussd_data *ud = ofono_ussd_get_data(ussd); ofono_ussd_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) { g_ril_print_response_no_args(ud->ril, message); CALLBACK_WITH_SUCCESS(cb, cbd->data); } else { CALLBACK_WITH_FAILURE(cb, cbd->data); } }
static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data) { DBG(""); struct cb_data *cbd = user_data; ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb; struct parcel rilp; int mode = OFONO_RADIO_ACCESS_MODE_ANY; int pref; if (message->error == RIL_E_SUCCESS) { ril_util_init_parcel(message, &rilp); /* first item in int[] is len so let's skip that */ parcel_r_int32(&rilp); pref = parcel_r_int32(&rilp); switch (pref) { case PREF_NET_TYPE_LTE_ONLY: mode = OFONO_RADIO_ACCESS_MODE_LTE; case PREF_NET_TYPE_GSM_ONLY: mode = OFONO_RADIO_ACCESS_MODE_GSM; break; case PREF_NET_TYPE_GSM_WCDMA_AUTO:/* according to UI design */ if (!cb) ril_force_rat_mode(cbd->user, pref); case PREF_NET_TYPE_WCDMA: case PREF_NET_TYPE_GSM_WCDMA: /* according to UI design */ mode = OFONO_RADIO_ACCESS_MODE_UMTS; break; case PREF_NET_TYPE_LTE_CDMA_EVDO: case PREF_NET_TYPE_LTE_GSM_WCDMA: case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA: if (!cb) ril_force_rat_mode(cbd->user, pref); break; case PREF_NET_TYPE_CDMA_EVDO_AUTO: case PREF_NET_TYPE_CDMA_ONLY: case PREF_NET_TYPE_EVDO_ONLY: case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO: default: break; } ofono_info("rat mode %d (ril %d)", mode, pref); if (cb) CALLBACK_WITH_SUCCESS(cb, mode, cbd->data); } else { if (cb) CALLBACK_WITH_FAILURE(cb, -1, cbd->data); ofono_error("rat mode query failed"); } }
static void ril_query_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_call_forwarding_query_cb_t cb = cbd->cb; struct ofono_call_forwarding_condition *list = NULL; struct parcel rilp; int nmbr_of_resps = 0; int i; if (message->error == RIL_E_SUCCESS) { ril_util_init_parcel(message, &rilp); nmbr_of_resps = parcel_r_int32(&rilp); list = g_new0( struct ofono_call_forwarding_condition, nmbr_of_resps); for (i = 0; i < nmbr_of_resps; i++) { const char *str; list[i].status = parcel_r_int32(&rilp); parcel_r_int32(&rilp); list[i].cls = parcel_r_int32(&rilp); list[i].phone_number.type = parcel_r_int32(&rilp); str = parcel_r_string(&rilp); if (str) { strncpy(list[i].phone_number.number, str, OFONO_MAX_PHONE_NUMBER_LENGTH); list[i].phone_number.number[ OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0'; list[i].time = parcel_r_int32(&rilp); } } CALLBACK_WITH_SUCCESS(cb, 1, list, cbd->data); g_free(list); } else
static void ril_set_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; struct ofono_call_settings *cs = cbd->user; struct settings_data *sd = ofono_call_settings_get_data(cs); ofono_call_settings_set_cb_t cb = cbd->cb; if (message->error == RIL_E_SUCCESS) { g_ril_print_response_no_args(sd->ril, message); CALLBACK_WITH_SUCCESS(cb, cbd->data); } else { CALLBACK_WITH_FAILURE(cb, cbd->data); } }
static void report_online(struct isi_data *isi, ofono_bool_t online) { struct isi_cb_data *cbd = isi->online_cbd; ofono_modem_online_cb_t cb = cbd->cb; isi->online_cbd = NULL; if (isi->online == online) CALLBACK_WITH_SUCCESS(cb, cbd->data); else CALLBACK_WITH_FAILURE(cb, cbd->data); g_free(cbd); }
static void uipaddr_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct ofono_gprs_context *gc = user_data; struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc); GAtResultIter iter; const char *gw = NULL; const char *netmask = NULL; DBG("ok %d", ok); if (!ok) { CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); return; } g_at_result_iter_init(&iter, result); while (g_at_result_iter_next(&iter, "+UIPADDR:")) { g_at_result_iter_skip_next(&iter); g_at_result_iter_skip_next(&iter); if (!g_at_result_iter_next_string(&iter, &gw)) break; if (!g_at_result_iter_next_string(&iter, &netmask)) break; } if (gw) ofono_gprs_context_set_ipv4_gateway(gc, gw); if (netmask) ofono_gprs_context_set_ipv4_netmask(gc, netmask); CALLBACK_WITH_SUCCESS(gcd->cb, gcd->cb_data); }
static void mtk_pin_retries_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sim_pin_retries_cb_t cb = cbd->cb; struct sim_data *sd = cbd->user; struct parcel rilp; char **strv; char *debug_str; int pin[MTK_EPINC_NUM_PASSWD]; int num_pin; if (message->error != RIL_E_SUCCESS) { ofono_error("Reply failure: %s", ril_error_to_string(message->error)); goto error; } g_ril_init_parcel(message, &rilp); strv = parcel_r_strv(&rilp); if (strv == NULL) { ofono_error("%s: parse error", __func__); goto error; } debug_str = g_strjoinv(",", strv); g_ril_append_print_buf(sd->ril, "{%d,%s}", g_strv_length(strv), debug_str); g_free(debug_str); g_ril_print_response(sd->ril, message); num_pin = sscanf(strv[0], "+EPINC:%d,%d,%d,%d", &pin[0], &pin[1], &pin[2], &pin[3]); g_strfreev(strv); if (num_pin != MTK_EPINC_NUM_PASSWD) goto error; sd->retries[OFONO_SIM_PASSWORD_SIM_PIN] = pin[0]; sd->retries[OFONO_SIM_PASSWORD_SIM_PIN2] = pin[1]; sd->retries[OFONO_SIM_PASSWORD_SIM_PUK] = pin[2]; sd->retries[OFONO_SIM_PASSWORD_SIM_PUK2] = pin[3]; CALLBACK_WITH_SUCCESS(cb, sd->retries, cbd->data); return; error: CALLBACK_WITH_FAILURE(cb, NULL, cbd->data); }