static mobileactivation_error_t mobileactivation_send_command_plist(mobileactivation_client_t client, plist_t command, plist_t *result) { if (!client || !command) return MOBILEACTIVATION_E_INVALID_ARG; plist_t cmd = plist_dict_get_item(command, "Command"); char* command_str = NULL; if (cmd) { plist_get_string_val(cmd, &command_str); } if (!command_str) return MOBILEACTIVATION_E_INVALID_ARG; mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; *result = NULL; ret = mobileactivation_error(property_list_service_send_binary_plist(client->parent, command)); plist_t dict = NULL; ret = mobileactivation_error(property_list_service_receive_plist(client->parent, &dict)); if (!dict) { debug_info("ERROR: Did not get reply for %s command", command_str); free(command_str); return MOBILEACTIVATION_E_PLIST_ERROR; } *result = dict; ret = mobileactivation_check_result(dict, command_str); free(command_str); return ret; }
/** * Get the home screen wallpaper as PNG data. * * @param client The connected sbservices client to use. * @param pngdata Pointer that will point to a newly allocated buffer * containing the PNG data upon successful return. It is up to the caller * to free the memory. * @param pngsize Pointer to a uint64_t that will be set to the size of the * buffer pngdata points to upon successful return. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or pngdata are invalid, or an SBSERVICES_E_* error * code otherwise. */ sbservices_error_t sbservices_get_home_screen_wallpaper_pngdata(sbservices_client_t client, char **pngdata, uint64_t *pngsize) { if (!client || !client->parent || !pngdata) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("getHomeScreenWallpaperPNGData")); sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); goto leave_unlock; } plist_free(dict); dict = NULL; res = sbservices_error(property_list_service_receive_plist(client->parent, &dict)); if (res == SBSERVICES_E_SUCCESS) { plist_t node = plist_dict_get_item(dict, "pngData"); if (node) { plist_get_data_val(node, pngdata, pngsize); } } leave_unlock: if (dict) { plist_free(dict); } sbs_unlock(client); return res; }
/** * Sets the icon state of the connected device. * * @param client The connected sbservices client to use. * @param newstate A plist containing the new iconstate. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or newstate is NULL, or an SBSERVICES_E_* error code otherwise. */ sbservices_error_t sbservices_set_icon_state(sbservices_client_t client, plist_t newstate) { if (!client || !client->parent || !newstate) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("setIconState")); plist_dict_insert_item(dict, "iconState", plist_copy(newstate)); sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); } /* NO RESPONSE */ if (dict) { plist_free(dict); } sbs_unlock(client); return res; }
webinspector_error_t webinspector_send(webinspector_client_t client, plist_t plist) { webinspector_error_t res = WEBINSPECTOR_E_UNKNOWN_ERROR; uint32_t offset = 0; int is_final_message = 0; char *packet = NULL; uint32_t packet_length = 0; debug_info("Sending webinspector message..."); debug_plist(plist); /* convert plist to packet */ plist_to_bin(plist, &packet, &packet_length); if (!packet || packet_length == 0) { debug_info("Error converting plist to binary."); return res; } do { /* determine if we need to send partial messages */ if (packet_length < WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE) { is_final_message = 1; } else { /* send partial packet */ is_final_message = 0; } plist_t outplist = plist_new_dict(); if (!is_final_message) { /* split packet into partial chunks */ plist_dict_set_item(outplist, "WIRPartialMessageKey", plist_new_data(packet + offset, WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE)); offset += WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE; packet_length -= WEBINSPECTOR_PARTIAL_PACKET_CHUNK_SIZE; } else { /* send final chunk */ plist_dict_set_item(outplist, "WIRFinalMessageKey", plist_new_data(packet + offset, packet_length)); offset += packet_length; packet_length -= packet_length; } res = webinspector_error(property_list_service_send_binary_plist(client->parent, outplist)); plist_free(outplist); outplist = NULL; if (res != WEBINSPECTOR_E_SUCCESS) { debug_info("Sending plist failed with error %d", res); return res; } } while(packet_length > 0); free(packet); packet = NULL; return res; }
/** * Generic device link service send function. * * @param client The device link service client to use for sending * @param plist The property list to send * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG when client or plist is NULL, * or DEVICE_LINK_SERVICE_E_MUX_ERROR when the given property list could * not be sent. */ device_link_service_error_t device_link_service_send(device_link_service_client_t client, plist_t plist) { if (!client || !plist) { return DEVICE_LINK_SERVICE_E_INVALID_ARG; } if (property_list_service_send_binary_plist(client->parent, plist) != PROPERTY_LIST_SERVICE_E_SUCCESS) { return DEVICE_LINK_SERVICE_E_MUX_ERROR; } return DEVICE_LINK_SERVICE_E_SUCCESS; }
heartbeat_error_t heartbeat_send(heartbeat_client_t client, plist_t plist) { heartbeat_error_t res = HEARTBEAT_E_UNKNOWN_ERROR; res = heartbeat_error(property_list_service_send_binary_plist(client->parent, plist)); if (res != HEARTBEAT_E_SUCCESS) { debug_info("Sending plist failed with error %d", res); return res; } debug_plist(plist); return res; }
/** * Sends a DLMessagePing plist. * * @param client The device link service client to use. * @param message String to send as ping message. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client or message is invalid, * or DEVICE_LINK_SERVICE_E_MUX_ERROR if the DLMessagePing plist could * not be sent. */ device_link_service_error_t device_link_service_send_ping(device_link_service_client_t client, const char *message) { if (!client || !client->parent || !message) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessagePing")); plist_array_append_item(array, plist_new_string(message)); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
/** * Performs a disconnect with the connected device link service client. * * @param client The device link service client to disconnect. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client is NULL, * or DEVICE_LINK_SERVICE_E_MUX_ERROR when there's an error when sending * the the disconnect message. */ device_link_service_error_t device_link_service_disconnect(device_link_service_client_t client) { if (!client) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageDisconnect")); plist_array_append_item(array, plist_new_string("All done, thanks for the memories")); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
/** * Sends a DLMessageProcessMessage plist. * * @param client The device link service client to use. * @param message PLIST_DICT to send. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client or message is invalid or * message is not a PLIST_DICT, or DEVICE_LINK_SERVICE_E_MUX_ERROR if * the DLMessageProcessMessage plist could not be sent. */ device_link_service_error_t device_link_service_send_process_message(device_link_service_client_t client, plist_t message) { if (!client || !client->parent || !message) return DEVICE_LINK_SERVICE_E_INVALID_ARG; if (plist_get_node_type(message) != PLIST_DICT) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageProcessMessage")); plist_array_append_item(array, plist_copy(message)); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
/** * Performs a disconnect with the connected device link service client. * * @param client The device link service client to disconnect. * @param message Optional message to send send to the device or NULL. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG if client is NULL, * or DEVICE_LINK_SERVICE_E_MUX_ERROR when there's an error when sending * the the disconnect message. */ device_link_service_error_t device_link_service_disconnect(device_link_service_client_t client, const char *message) { if (!client) return DEVICE_LINK_SERVICE_E_INVALID_ARG; plist_t array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageDisconnect")); if (message) plist_array_append_item(array, plist_new_string(message)); else plist_array_append_item(array, plist_new_string("___EmptyParameterString___")); device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { err = DEVICE_LINK_SERVICE_E_MUX_ERROR; } plist_free(array); return err; }
/** * Gets the icon state of the connected device. * * @param client The connected sbservices client to use. * @param state Pointer that will point to a newly allocated plist containing * the current icon state. It is up to the caller to free the memory. * @param format_version A string to be passed as formatVersion along with * the request, or NULL if no formatVersion should be passed. This is only * supported since iOS 4.0 so for older firmware versions this must be set * to NULL. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or state is invalid, or an SBSERVICES_E_* error code otherwise. */ sbservices_error_t sbservices_get_icon_state(sbservices_client_t client, plist_t *state, const char *format_version) { if (!client || !client->parent || !state) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("getIconState")); if (format_version) { plist_dict_insert_item(dict, "formatVersion", plist_new_string(format_version)); } sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); goto leave_unlock; } plist_free(dict); dict = NULL; res = sbservices_error(property_list_service_receive_plist(client->parent, state)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not get icon state, error %d", res); if (*state) { plist_free(*state); *state = NULL; } } leave_unlock: if (dict) { plist_free(dict); } sbs_unlock(client); return res; }
/** * Gets the interface orientation of the device. * * @param client The connected sbservices client to use. * @param interface_orientation The interface orientation upon successful return. * * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when * client or state is invalid, or an SBSERVICES_E_* error code otherwise. */ sbservices_error_t sbservices_get_interface_orientation(sbservices_client_t client, sbservices_interface_orientation_t* interface_orientation) { if (!client || !client->parent || !interface_orientation) return SBSERVICES_E_INVALID_ARG; sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "command", plist_new_string("getInterfaceOrientation")); sbs_lock(client); res = sbservices_error(property_list_service_send_binary_plist(client->parent, dict)); if (res != SBSERVICES_E_SUCCESS) { debug_info("could not send plist, error %d", res); goto leave_unlock; } plist_free(dict); dict = NULL; res = sbservices_error(property_list_service_receive_plist(client->parent, &dict)); if (res == SBSERVICES_E_SUCCESS) { plist_t node = plist_dict_get_item(dict, "interfaceOrientation"); if (node) { uint64_t value = SBSERVICES_INTERFACE_ORIENTATION_UNKNOWN; plist_get_uint_val(node, &value); *interface_orientation = (sbservices_interface_orientation_t)value; } } leave_unlock: if (dict) { plist_free(dict); } sbs_unlock(client); return res; }
/** * Performs the DLMessageVersionExchange with the connected device. * This should be the first operation to be executed by an implemented * device link service client. * * @param client The device_link_service client to use. * @param version_major The major version number to check. * @param version_minor The minor version number to check. * * @return DEVICE_LINK_SERVICE_E_SUCCESS on success, * DEVICE_LINK_SERVICE_E_INVALID_ARG when client is NULL, * DEVICE_LINK_SERVICE_E_MUX_ERROR when a communication error occurs, * DEVICE_LINK_SERVICE_E_PLIST_ERROR when the received plist has not the * expected contents, DEVICE_LINK_SERVICE_E_BAD_VERSION when the version * given by the device is larger than the given version, * or DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR otherwise. */ device_link_service_error_t device_link_service_version_exchange(device_link_service_client_t client, uint64_t version_major, uint64_t version_minor) { if (!client) return DEVICE_LINK_SERVICE_E_INVALID_ARG; device_link_service_error_t err = DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR; /* perform version exchange */ plist_t array = NULL; char *msg = NULL; /* receive DLMessageVersionExchange from device */ if (property_list_service_receive_plist(client->parent, &array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("Did not receive initial message from device!"); err = DEVICE_LINK_SERVICE_E_MUX_ERROR; goto leave; } msg = device_link_service_get_message(array); if (!msg || strcmp(msg, "DLMessageVersionExchange")) { debug_info("Did not receive DLMessageVersionExchange from device!"); err = DEVICE_LINK_SERVICE_E_PLIST_ERROR; goto leave; } free(msg); msg = NULL; /* get major and minor version number */ if (plist_array_get_size(array) < 3) { debug_info("DLMessageVersionExchange has unexpected format!"); err = DEVICE_LINK_SERVICE_E_PLIST_ERROR; goto leave; } plist_t maj = plist_array_get_item(array, 1); plist_t min = plist_array_get_item(array, 2); uint64_t vmajor = 0; uint64_t vminor = 0; if (maj) { plist_get_uint_val(maj, &vmajor); } if (min) { plist_get_uint_val(min, &vminor); } if (vmajor > version_major) { debug_info("Version mismatch: device=(%lld,%lld) > expected=(%lld,%lld)", vmajor, vminor, version_major, version_minor); err = DEVICE_LINK_SERVICE_E_BAD_VERSION; goto leave; } else if ((vmajor == version_major) && (vminor > version_minor)) { debug_info("WARNING: Version mismatch: device=(%lld,%lld) > expected=(%lld,%lld)", vmajor, vminor, version_major, version_minor); err = DEVICE_LINK_SERVICE_E_BAD_VERSION; goto leave; } plist_free(array); /* version is ok, send reply */ array = plist_new_array(); plist_array_append_item(array, plist_new_string("DLMessageVersionExchange")); plist_array_append_item(array, plist_new_string("DLVersionsOk")); plist_array_append_item(array, plist_new_uint(version_major)); if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("Error when sending DLVersionsOk"); err = DEVICE_LINK_SERVICE_E_MUX_ERROR; goto leave; } plist_free(array); /* receive DeviceReady message */ array = NULL; if (property_list_service_receive_plist(client->parent, &array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("Error when receiving DLMessageDeviceReady!"); err = DEVICE_LINK_SERVICE_E_MUX_ERROR; goto leave; } msg = device_link_service_get_message(array); if (!msg || strcmp(msg, "DLMessageDeviceReady")) { debug_info("Did not get DLMessageDeviceReady!"); err = DEVICE_LINK_SERVICE_E_PLIST_ERROR; goto leave; } err = DEVICE_LINK_SERVICE_E_SUCCESS; leave: if (msg) { free(msg); } if (array) { plist_free(array); } return err; }