Пример #1
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void acm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
			      int rc ) {
	struct acm_device *acm = container_of ( ep, struct acm_device,
						usbnet.in );
	struct rndis_device *rndis = acm->rndis;

	/* Profile receive completions */
	profile_start ( &acm_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto ignore;

	/* Record USB errors against the RNDIS device */
	if ( rc != 0 ) {
		DBGC ( acm, "ACM %p bulk IN failed: %s\n",
		       acm, strerror ( rc ) );
		goto error;
	}

	/* Hand off to RNDIS */
	rndis_rx ( rndis, iob_disown ( iobuf ) );

	profile_stop ( &acm_in_profiler );
	return;

 error:
	rndis_rx_err ( rndis, iob_disown ( iobuf ), rc );
 ignore:
	free_iob ( iobuf );
}
Пример #2
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_in_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.in );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_rx_header *header;

	/* Profile completions */
	profile_start ( &smsc95xx_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p bulk IN failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p underlength bulk IN\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check for errors */
	if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT |
					     SMSC95XX_RX_LATE |
					     SMSC95XX_RX_CRC ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p receive error (%08x):\n",
		       smsc95xx, le32_to_cpu ( header->command ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );

	profile_stop ( &smsc95xx_in_profiler );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Пример #3
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_in_complete ( struct usb_endpoint *ep,
				 struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.in );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_rx_header *header;

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
		       dm96xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check status */
	if ( header->rsr & ~DM96XX_RSR_MF ) {
		DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
		       dm96xx, header->rsr );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Пример #4
0
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void acm_intr_complete ( struct usb_endpoint *ep,
				struct io_buffer *iobuf, int rc ) {
	struct acm_device *acm = container_of ( ep, struct acm_device,
						usbnet.intr );
	struct rndis_device *rndis = acm->rndis;
	struct usb_setup_packet *message;

	/* Profile completions */
	profile_start ( &acm_intr_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto ignore;

	/* Drop packets with errors */
	if ( rc != 0 ) {
		DBGC ( acm, "ACM %p interrupt failed: %s\n",
		       acm, strerror ( rc ) );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		goto error;
	}

	/* Extract message header */
	if ( iob_len ( iobuf ) < sizeof ( *message ) ) {
		DBGC ( acm, "ACM %p underlength interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto error;
	}
	message = iobuf->data;

	/* Parse message header */
	switch ( message->request ) {

	case cpu_to_le16 ( CDC_RESPONSE_AVAILABLE ) :
	case cpu_to_le16 ( 0x0001 ) : /* qemu seems to use this value */
		acm->responded = 1;
		break;

	default:
		DBGC ( acm, "ACM %p unrecognised interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -ENOTSUP;
		goto error;
	}

	/* Free I/O buffer */
	free_iob ( iobuf );
	profile_stop ( &acm_intr_profiler );

	return;

 error:
	rndis_rx_err ( rndis, iob_disown ( iobuf ), rc );
 ignore:
	free_iob ( iobuf );
	return;
}
Пример #5
0
/**
 * Receive control packet
 *
 * @v acm		USB RNDIS device
 * @ret rc		Return status code
 */
static int acm_control_receive ( struct acm_device *acm ) {
	struct rndis_device *rndis = acm->rndis;
	struct usb_device *usb = acm->usb;
	struct io_buffer *iobuf;
	struct rndis_header *header;
	size_t mtu = ACM_RESPONSE_MTU;
	size_t len;
	int rc;

	/* Allocate I/O buffer */
	iobuf = alloc_iob ( mtu );
	if ( ! iobuf ) {
		rc = -ENOMEM;
		goto err_alloc;
	}

	/* Get encapsulated response */
	if ( ( rc = cdc_get_encapsulated_response ( usb, acm->usbnet.comms,
						    iobuf->data, mtu ) ) != 0 ){
		DBGC ( acm, "ACM %p could not get encapsulated response: %s\n",
		       acm, strerror ( rc ) );
		goto err_get_response;
	}

	/* Fix up buffer length */
	header = iobuf->data;
	len = le32_to_cpu ( header->len );
	if ( len > mtu ) {
		DBGC ( acm, "ACM %p overlength encapsulated response\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, mtu );
		rc = -EPROTO;
		goto err_len;
	}
	iob_put ( iobuf, len );

	/* Hand off to RNDIS */
	rndis_rx ( rndis, iob_disown ( iobuf ) );

	return 0;

 err_len:
 err_get_response:
	free_iob ( iobuf );
 err_alloc:
	return rc;
}