Пример #1
0
/**
 * This function is called by the Gadget Driver for each EP to be
 * configured for the current configuration (SET_CONFIGURATION).
 *
 * This function initializes the dwc_otg_ep_t data structure, and then
 * calls dwc_otg_ep_activate.
 */
static int ep_enable(struct usb_ep *usb_ep,
		     const struct usb_endpoint_descriptor *ep_desc)
{
	int retval;

	DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);

	if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
		DWC_WARN("%s, bad ep or descriptor\n", __func__);
		return -EINVAL;
	}
	if (usb_ep == &gadget_wrapper->ep0) {
		DWC_WARN("%s, bad ep(0)\n", __func__);
		return -EINVAL;
	}

	/* Check FIFO size? */
	if (!ep_desc->wMaxPacketSize) {
		DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
		return -ERANGE;
	}

	if (!gadget_wrapper->driver ||
	    gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
		DWC_WARN("%s, bogus device state\n", __func__);
		return -ESHUTDOWN;
	}

	retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
				       (const uint8_t *)ep_desc,
				       (void *)usb_ep);
	if (retval) {
		DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
		return -EINVAL;
	}

	usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);

	return 0;
}
Пример #2
0
/**
 * This function initialized the usb_ep structures to there default
 * state.
 *
 * @param d Pointer on gadget_wrapper.
 */
void gadget_add_eps(struct gadget_wrapper *d)
{
	static const char *names[] = {

		"ep0",
		"ep1in",
		"ep2in",
		"ep3in",
		"ep4in",
		"ep5in",
		"ep6in",
		"ep7in",
		"ep8in",
		"ep9in",
		"ep10in",
		"ep11in",
		"ep12in",
		"ep13in",
		"ep14in",
		"ep15in",
		"ep1out",
		"ep2out",
		"ep3out",
		"ep4out",
		"ep5out",
		"ep6out",
		"ep7out",
		"ep8out",
		"ep9out",
		"ep10out",
		"ep11out",
		"ep12out",
		"ep13out",
		"ep14out",
		"ep15out"
	};

	int i;
	struct usb_ep *ep;

	DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);

	INIT_LIST_HEAD(&d->gadget.ep_list);
	d->gadget.ep0 = &d->ep0;
	d->gadget.speed = USB_SPEED_UNKNOWN;

	INIT_LIST_HEAD(&d->gadget.ep0->ep_list);

	/**
	 * Initialize the EP0 structure.
	 */
	ep = &d->ep0;

	/* Init the usb_ep structure. */
	ep->name = names[0];
	ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;

	/**
	 * @todo NGS: What should the max packet size be set to
	 * here?  Before EP type is set?
	 */
	ep->maxpacket = MAX_PACKET_SIZE;
	dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);

	list_add_tail(&ep->ep_list, &d->gadget.ep_list);

	/**
	 * Initialize the EP structures.
	 */

	for (i = 0; i < 15; i++) {
		ep = &d->in_ep[i];

		/* Init the usb_ep structure. */
		ep->name = names[i + 1];
		ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;

		/**
		 * @todo NGS: What should the max packet size be set to
		 * here?  Before EP type is set?
		 */
		ep->maxpacket = MAX_PACKET_SIZE;
		list_add_tail(&ep->ep_list, &d->gadget.ep_list);
	}

	for (i = 0; i < 15; i++) {
		ep = &d->out_ep[i];

		/* Init the usb_ep structure. */
		ep->name = names[15 + i + 1];
		ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;

		/**
		 * @todo NGS: What should the max packet size be set to
		 * here?  Before EP type is set?
		 */
		ep->maxpacket = MAX_PACKET_SIZE;

		list_add_tail(&ep->ep_list, &d->gadget.ep_list);
	}

	/* remove ep0 from the list.  There is a ep0 pointer. */
	list_del_init(&d->ep0.ep_list);

	d->ep0.maxpacket = MAX_EP0_SIZE;
}
Пример #3
0
static int _setup(dwc_otg_pcd_t *pcd, uint8_t *bytes)
{
	DWC_DEBUGPL(DBG_PCD, "%s(): enter \n", __func__);

	const usb_device_request_t *ctrlReq = (usb_device_request_t *)bytes;

	int value = 0;
	int idx;
	usb_device_request_t ctrlConvertedReq;
	usb_device_request_t *ctrl = &ctrlConvertedReq;


	ctrl->bmRequestType = (uByte)(ctrlReq->bmRequestType);
	ctrl->bRequest = (uByte)(ctrlReq->bRequest);
	ctrl->wValue[0] = ctrlReq->wValue[0];
	ctrl->wValue[1] = ctrlReq->wValue[1];
	ctrl->wIndex[0] = ctrlReq->wIndex[0];
	ctrl->wIndex[1] = ctrlReq->wIndex[1];
	ctrl->wLength[0] = ctrlReq->wLength[0];
	ctrl->wLength[1] = ctrlReq->wLength[1];
	/*
	 * usually this stores reply data in the pre-allocated ep0 buffer,
	 * but config change events will reconfigure hardware.
	 */
	static_data->dl_req.data.zero = 0;
	if (UT_GET_RECIPIENT(ctrl->bmRequestType) == UT_INTERFACE) {
		if ((UT_GET_DIR(ctrl->bmRequestType) == UT_WRITE)
		    && (UGETW(ctrl->wLength) > 0)) {
			static_data->dl_req.data.buf =
				&static_data->ep0_buffer[0];
			DWC_MEMCPY(&static_data->dl_req.out_req, ctrl,
				   sizeof(*ctrl));
			static_data->dl_req.data.length =
				DWC_MIN(UGETW(
						ctrl->wLength),
					static_data->ep0_buffer_size);

			// either shorter than asked, or multiple of the MPS require ZLP.
			static_data->dl_req.data.zero =
				((value < UGETW(ctrl->wLength))
				 &&
				 ((value %
				   pcd->ep0.dwc_ep.
				   maxpacket) ==
				  0)) ? 1 : 0;

			// Elaborate when getting the time.
			dwc_otg_pcd_ep_queue(
				pcd, /*void* ep_hanlde */ NULL,
				static_data->dl_req.data.buf,
				(dwc_dma_t)static_data->dl_req.
				data.buf,
				static_data->dl_req.data.length,
				static_data->dl_req.data.zero,
			        /*void* req_handle */ &static_data
				->dl_req, 0);
		} else {
			static_data->dl_req.data.buf =
				&static_data->ep0_buffer[0];
			if (static_data->usb_class_handler(ctrl, &value,
							   &static_data->dl_req
							   .data.buf) != 0) {
				value = -DWC_E_NOT_SUPPORTED;
			}
		}
	} else {
		switch (ctrl->bRequest) {
		case UR_GET_DESCRIPTOR:
			__DWC_ERROR("ctrl->Length = %d \n",
				    UGETW(ctrl->wLength));

			switch (UGETW(ctrl->wValue) >> 8) {
			case UDESC_DEVICE:
				value =
					DWC_MIN(UGETW(ctrl->wLength),
						USB_DEVICE_DESCRIPTOR_SIZE);
				static_data->dl_req.data.buf = (uint8_t *)
							       static_data->
							       usb_device_descriptor;

				break;

			case UDESC_CONFIG:
				value = DWC_MIN(UGETW(ctrl->wLength),
						UGETW(static_data->
						      usb_config_descriptor->
						      wTotalLength));
				static_data->dl_req.data.buf = (uint8_t *)
							       static_data->
							       usb_config_descriptor;

				break;

			case UDESC_OTHER_SPEED_CONFIGURATION:
				__DWC_ERROR
				(
					"UDESC_OTHER_SPEED_CONFIGURATION NOT IMPLEMENTED! \n");
				break;

			case UDESC_STRING:
				/* wIndex == language code.
				 * this driver only handles one language, you can
				 * add string tables for other languages, using
				 * any UTF-8 characters
				 */
				idx = UGETW(ctrl->wValue) & 0xFF;
				__DWC_ERROR("UDESC_STRING idx = %d \n", idx);
				__DWC_ERROR(
					"UDESC_STRING bLength = %d \n",
					&static_data->strings_desc[idx].
					bLength);
				if (idx > static_data->usb_strings_count) {
					if (idx == 0xEE) {
						// Microsoft MTP extension
						value = 0;
					} else {
						value = -DWC_E_INVALID;
					}
				} else {
					value = DWC_MIN(UGETW(
								ctrl->wLength),
							static_data->
							strings_desc[idx].
							bLength);
					static_data->dl_req.data.buf =
						(uint8_t *)
						&
						static_data->strings_desc[idx];
				}

				break;
			}
			break;

		case UR_SET_CONFIG:
			static_data->usb_config = UGETW(ctrl->wValue);
			value = 0;

			{
				int i;
				for (i = 0;
				     i < static_data->usb_num_endpoints;
				     i++) {
					int ret = dwc_otg_pcd_ep_enable(
						pcd,
						(const
						 uint8_t
						 *)&static_data->usb_endpoints[
							i],
						static_data
						->usb_endpoints[i].
						bEndpointAddress);
					__DWC_WARN(
						"Enabled endpoint: %x ret: %d\n",
						static_data->usb_endpoints[i
						].bEndpointAddress,
						ret);
				}
				struct usb_event evt;
				evt.event = USB_EVENT_SET_CONFIG;
				evt.event_data.config = static_data->usb_config;
				if (static_data->usb_event_cb) {
					static_data->usb_event_cb(&evt);
				}
			}

			break;
		case UR_GET_CONFIG:
			static_data->dl_req.data.buf = &static_data->usb_config;
			value = DWC_MIN(UGETW(ctrl->wLength), 1);
			break;

		/* until we add altsetting support, or other interfaces,
		 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
		 * and already killed pending endpoint I/O.
		 */
		case UR_SET_INTERFACE:
			value = 0;
			break;

		case UR_GET_INTERFACE:
			__DWC_ERROR("UR_GET_INTERFACE NOT IMPLEMENTED! \n");
			goto unknown;
			break;

		default:
unknown:

			value = -DWC_E_NOT_SUPPORTED;
			break;
		}
	}
	/* respond with data transfer before status phase? */
	__DWC_ERROR("%s(): req.length = %d - max length is 64 \n", __func__,
		    value);
	if (value >= 0) {
		static_data->dl_req.data.length = value;

		// either shorter than asked, or multiple of the MPS require ZLP.
		static_data->dl_req.data.zero = ((value < UGETW(ctrl->wLength))
						 && ((value %
						      pcd->ep0.dwc_ep.maxpacket)
						     ==
						     0)) ? 1 : 0;

		// Elaborate when getting the time.
		dwc_otg_pcd_ep_queue(pcd, /*void* ep_hanlde */ NULL,
				     static_data->dl_req.data.buf,
				     (dwc_dma_t)static_data->dl_req.data.buf,
				     static_data->dl_req.data.length,
				     static_data->dl_req.data.zero,
		                     /*void* req_handle */ NULL, 0);
	}

	/* device either stalls (value < 0) or reports success */
	return value;
}