Example #1
0
/**
 * dfu_target_use_alt_setting:
 * @target: a #DfuTarget
 * @error: a #GError, or %NULL
 *
 * Opens a DFU-capable target.
 *
 * Return value: %TRUE for success
 *
 * Since: 0.5.4
 **/
static gboolean
dfu_target_use_alt_setting (DfuTarget *target, GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	GUsbDevice *dev;
	g_autoptr(GError) error_local = NULL;

	g_return_val_if_fail (DFU_IS_TARGET (target), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	/* use the correct setting */
	dev = dfu_device_get_usb_dev (priv->device);
	if (dfu_device_get_mode (priv->device) == DFU_MODE_DFU) {
		if (!g_usb_device_set_interface_alt (dev,
						     (gint) dfu_device_get_interface (priv->device),
						     (gint) priv->alt_setting,
						     &error_local)) {
			g_set_error (error,
				     DFU_ERROR,
				     DFU_ERROR_NOT_SUPPORTED,
				     "cannot set alternate setting 0x%02x on interface %i: %s",
				     priv->alt_setting,
				     dfu_device_get_interface (priv->device),
				     error_local->message);
			return FALSE;
		}
	}

	return TRUE;
}
Example #2
0
static gchar *
dfu_context_get_device_id (DfuDevice *device)
{
	GUsbDevice *dev;
	dev = dfu_device_get_usb_dev (device);
	if (dev == NULL)
		return g_strdup (dfu_device_get_platform_id (device));
	return g_strdup_printf ("%04x:%04x [%s]",
				g_usb_device_get_vid (dev),
				g_usb_device_get_pid (dev),
				g_usb_device_get_platform_id (dev));
}
Example #3
0
/**
 * dfu_target_setup:
 * @target: a #DfuTarget
 * @error: a #GError, or %NULL
 *
 * Opens a DFU-capable target.
 *
 * Return value: %TRUE for success
 *
 * Since: 0.5.4
 **/
static gboolean
dfu_target_setup (DfuTarget *target, GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	g_autoptr(GError) error_local = NULL;

	g_return_val_if_fail (DFU_IS_TARGET (target), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	/* already done */
	if (priv->done_setup)
		return TRUE;

	/* get string */
	if (priv->alt_idx != 0x00) {
		GUsbDevice *dev;
		dev = dfu_device_get_usb_dev (priv->device);
		priv->alt_name =
			g_usb_device_get_string_descriptor (dev,
							    priv->alt_idx,
							    NULL);
	}

	/* parse the DfuSe format according to UM0424 */
	if (!dfu_target_parse_sectors (target,
				       priv->alt_name,
				       error))
		return FALSE;

	/* add a dummy entry */
	if (priv->sectors->len == 0) {
		DfuSector *sector;
		sector = dfu_sector_new (0x0, /* addr */
					 0x0, /* size */
					 0x0, /* size_left */
					 0x0, /* zone */
					 0x0, /* number */
					 DFU_SECTOR_CAP_READABLE |
					 DFU_SECTOR_CAP_WRITEABLE);
		g_debug ("no UM0424 sector descripton in %s", priv->alt_name);
		g_ptr_array_add (priv->sectors, sector);
	}

	priv->done_setup = TRUE;
	return TRUE;
}
Example #4
0
/**
 * dfu_context_get_device_by_vid_pid:
 * @context: a #DfuContext
 * @vid: a vendor ID
 * @pid: a product ID
 * @error: a #GError, or %NULL
 *
 * Finds a device in the context with a specific vendor:product ID.
 * An error is returned if more than one device matches.
 *
 * Return value: (transfer full): a #DfuDevice for success, or %NULL for an error
 *
 * Since: 0.5.4
 **/
DfuDevice *
dfu_context_get_device_by_vid_pid (DfuContext *context,
				   guint16 vid, guint16 pid,
				   GError **error)
{
	DfuContextPrivate *priv = GET_PRIVATE (context);
	DfuContextItem *item;
	DfuDevice *device = NULL;
	GUsbDevice *dev;
	guint i;

	g_return_val_if_fail (DFU_IS_CONTEXT (context), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	/* search all devices */
	for (i = 0; i < priv->devices->len; i++) {

		/* match */
		item = g_ptr_array_index (priv->devices, i);
		dev = dfu_device_get_usb_dev (item->device);
		if (g_usb_device_get_vid (dev) == vid &&
		    g_usb_device_get_pid (dev) == pid) {
			if (device != NULL) {
				g_set_error (error,
					     DFU_ERROR,
					     DFU_ERROR_INVALID_DEVICE,
					     "multiple device matches for %04x:%04x",
					     vid, pid);
				return NULL;
			}
			device = item->device;
			continue;
		}
	}
	if (device == NULL) {
		g_set_error (error,
			     DFU_ERROR,
			     DFU_ERROR_NOT_FOUND,
			     "no device matches for %04x:%04x",
			     vid, pid);
		return NULL;
	}
	return g_object_ref (device);
}
Example #5
0
/**
 * dfu_target_upload_chunk: (skip)
 **/
GBytes *
dfu_target_upload_chunk (DfuTarget *target, guint8 index,
			 GCancellable *cancellable, GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	g_autoptr(GError) error_local = NULL;
	guint8 *buf;
	gsize actual_length;
	guint16 transfer_size = dfu_device_get_transfer_size (priv->device);

	buf = g_new0 (guint8, transfer_size);
	if (!g_usb_device_control_transfer (dfu_device_get_usb_dev (priv->device),
					    G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
					    G_USB_DEVICE_REQUEST_TYPE_CLASS,
					    G_USB_DEVICE_RECIPIENT_INTERFACE,
					    DFU_REQUEST_UPLOAD,
					    index,
					    dfu_device_get_interface (priv->device),
					    buf, (gsize) transfer_size,
					    &actual_length,
					    dfu_device_get_timeout (priv->device),
					    cancellable,
					    &error_local)) {
		/* refresh the error code */
		dfu_device_error_fixup (priv->device, cancellable, &error_local);
		g_set_error (error,
			     DFU_ERROR,
			     DFU_ERROR_NOT_SUPPORTED,
			     "cannot upload data: %s",
			     error_local->message);
		return NULL;
	}

	/* for ST devices, the action only occurs when we do GetStatus */
	if (!dfu_device_has_quirk (priv->device, DFU_DEVICE_QUIRK_NO_GET_STATUS_UPLOAD)) {
		if (!dfu_target_check_status (target, cancellable, error))
			return FALSE;
	}

	return g_bytes_new_take (buf, actual_length);
}
Example #6
0
/**
 * dfu_target_download_chunk:
 **/
static gboolean
dfu_target_download_chunk (DfuTarget *target, guint8 index, GBytes *bytes,
			   GCancellable *cancellable, GError **error)
{
	DfuTargetPrivate *priv = GET_PRIVATE (target);
	g_autoptr(GError) error_local = NULL;
	gsize actual_length;

	if (!g_usb_device_control_transfer (dfu_device_get_usb_dev (priv->device),
					    G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
					    G_USB_DEVICE_REQUEST_TYPE_CLASS,
					    G_USB_DEVICE_RECIPIENT_INTERFACE,
					    DFU_REQUEST_DNLOAD,
					    index,
					    dfu_device_get_interface (priv->device),
					    (guint8 *) g_bytes_get_data (bytes, NULL),
					    g_bytes_get_size (bytes),
					    &actual_length,
					    dfu_device_get_timeout (priv->device),
					    cancellable,
					    &error_local)) {
		/* refresh the error code */
		dfu_device_error_fixup (priv->device, cancellable, &error_local);
		g_set_error (error,
			     DFU_ERROR,
			     DFU_ERROR_NOT_SUPPORTED,
			     "cannot download data: %s",
			     error_local->message);
		return FALSE;
	}

	/* for ST devices, the action only occurs when we do GetStatus */
	if (!dfu_target_check_status (target, cancellable, error))
		return FALSE;

	g_assert (actual_length == g_bytes_get_size (bytes));
	return TRUE;
}