/**
* @brief  CDC_InterfaceDeInit 
*         The function DeInit the Host Channels used for the CDC class.
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval None
*/
void CDC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
                          void *phost)
{
  if ( CDC_Machine.CDC_CommItf.hc_num_in)
  {
    USB_OTG_HC_Halt(pdev, CDC_Machine.CDC_CommItf.hc_num_in);
    USBH_Free_Channel  (pdev,CDC_Machine.CDC_CommItf.hc_num_in);
    CDC_Machine.CDC_CommItf.hc_num_in = 0;     /* Reset the Channel as Free */
  }
  
  if ( CDC_Machine.CDC_DataItf.hc_num_out)
  {
    USB_OTG_HC_Halt(pdev, CDC_Machine.CDC_DataItf.hc_num_out);
    USBH_Free_Channel  (pdev,CDC_Machine.CDC_DataItf.hc_num_out);
    CDC_Machine.CDC_DataItf.hc_num_out = 0;     /* Reset the Channel as Free */
  }
  
  if ( CDC_Machine.CDC_DataItf.hc_num_in)
  {
    USB_OTG_HC_Halt(pdev, CDC_Machine.CDC_DataItf.hc_num_in);
    USBH_Free_Channel  (pdev,CDC_Machine.CDC_DataItf.hc_num_in);
    CDC_Machine.CDC_DataItf.hc_num_in = 0;     /* Reset the Channel as Free */
  } 
//  return USBH_OK;
}
/**
* @brief  USBH_MSC_InterfaceDeInit 
*         De-Initialize interface by freeing host channels allocated to interface
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval None
*/
void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
							   void *phost)
{	
	if ( MSC_Machine.hc_num_out)
	{
		USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_out);
		USBH_Free_Channel  (pdev, MSC_Machine.hc_num_out);
		MSC_Machine.hc_num_out = 0;     /* Reset the Channel as Free */
	}

	if ( MSC_Machine.hc_num_in)
	{
		USB_OTG_HC_Halt(pdev, MSC_Machine.hc_num_in);
		USBH_Free_Channel  (pdev, MSC_Machine.hc_num_in);
		MSC_Machine.hc_num_in = 0;     /* Reset the Channel as Free */
	} 
}
예제 #3
0
/**
  * @brief  USBH_MSC_InterfaceDeInit 
  *         De-Initialize interface by freeing host channels allocated to interface
  * @param  pdev: Selected device
  * @param  hdev: Selected device property
  * @retval None
  */
void USBH_MSC_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
                                USBH_DeviceProp_TypeDef *hdev)
{	
  if ( MSC_Machine.hc_num_out)
  {
    USB_OTG_HC_Halt((&USB_OTG_FS_dev), MSC_Machine.hc_num_out);
    USBH_Free_Channel  (pdev, MSC_Machine.hc_num_out);
    MSC_Machine.hc_num_out = 0;     /* Reset the Channel as Free */
  }
   
  if ( MSC_Machine.hc_num_in)
  {
    USB_OTG_HC_Halt((&USB_OTG_FS_dev), MSC_Machine.hc_num_in);
    USBH_Free_Channel  (pdev, MSC_Machine.hc_num_in);
    MSC_Machine.hc_num_in = 0;     /* Reset the Channel as Free */
  } 
}
예제 #4
0
USBH_Status USBH_Dev_DefaultCB_Task(USB_OTG_CORE_HANDLE *pcore , USBH_DEV *pdev)
{
	// this is called periodically until the device state machine changes

	char isDevRoot = pdev->Parent == 0;
	if (isDevRoot == 0) {
		// since this device now has an address
		// we can let the hub handle new devices on another port
		USBH_DEV* parentHub = (USBH_DEV*)pdev->Parent;
		Hub_Data_t* hubData = (Hub_Data_t*)parentHub->Usr_Data;
		hubData->port_busy = 0;
		// this is a useless device, free the channel so another dev can use them
		USBH_Free_Channel(pcore, &(pdev->Control.hc_num_in));
		USBH_Free_Channel(pcore, &(pdev->Control.hc_num_out));
	}

	return USBH_OK;
}
예제 #5
0
/**
  * @brief  USBH_DeInit
  *         Re-Initialize Host
  * @param  None
  * @retval status: USBH_Status
  */
USBH_Status USBH_DeInit(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost)
{
  /* Software Init */

  phost->gState = HOST_IDLE;
  phost->gStateBkp = HOST_IDLE;
  phost->EnumState = ENUM_IDLE;
  phost->RequestState = CMD_SEND;

  phost->Control.state = CTRL_SETUP;
  phost->Control.ep0size = USB_OTG_MAX_EP0_SIZE;

  phost->device_prop.address = USBH_DEVICE_ADDRESS_DEFAULT;
  phost->device_prop.speed = HPRT0_PRTSPD_FULL_SPEED;

  USBH_Free_Channel  (pdev, phost->Control.hc_num_in);
  USBH_Free_Channel  (pdev, phost->Control.hc_num_out);
  return USBH_OK;
}
예제 #6
0
/**
* @brief  USBH_HID_InterfaceDeInit 
*         The function DeInit the Host Channels used for the HID class.
* @param  pdev: Selected device
* @param  hdev: Selected device property
* @retval None
*/
void USBH_HID_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
                               void *phost)
{	
   //USBH_HOST *pphost = phost;
    
  if(HID_Machine.hc_num_in != 0x00)
  {   
    USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_in);
    USBH_Free_Channel  (pdev, HID_Machine.hc_num_in);
    HID_Machine.hc_num_in = 0;     /* Reset the Channel as Free */  
  }
  
  if(HID_Machine.hc_num_out != 0x00)
  {   
    USB_OTG_HC_Halt(pdev, HID_Machine.hc_num_out);
    USBH_Free_Channel  (pdev, HID_Machine.hc_num_out);
    HID_Machine.hc_num_out = 0;     /* Reset the Channel as Free */  
  }
 
  start_toggle = 0;
}
예제 #7
0
// The function DeInit the Host Channels used for the HID class.
void USBH_HID_InterfaceDeInit ( USB_OTG_CORE_HANDLE *pdev,
                               void *phost)
{
  HID_Machine_TypeDef *HID_Machine = &HID_Machines[pdev->cfg.coreID];	
   //USBH_HOST *pphost = phost;
    
  if(HID_Machine->hc_num_in != 0x00)
  {   
    USB_OTG_HC_Halt(pdev, HID_Machine->hc_num_in);
    USBH_Free_Channel  (pdev, HID_Machine->hc_num_in);
    HID_Machine->hc_num_in = 0;     /* Reset the Channel as Free */  
  }
  
  if(HID_Machine->hc_num_out != 0x00)
  {   
    USB_OTG_HC_Halt(pdev, HID_Machine->hc_num_out);
    USBH_Free_Channel  (pdev, HID_Machine->hc_num_out);
    HID_Machine->hc_num_out = 0;     /* Reset the Channel as Free */  
  }
 
  start_toggles[pdev->cfg.coreID] = 0;
}
예제 #8
0
/**
 * This function will free a pipe, it will release all resouces of the pipe.
 *
 * @param pipe the pipe handler to be free.
 * 
 * @return the error code, RT_EOK on successfully.
 */
static rt_err_t susb_free_pipe(upipe_t pipe)
{
    rt_uint8_t channel;

    RT_ASSERT(pipe != RT_NULL);
    
    RT_DEBUG_LOG(RT_DEBUG_USB, ("susb_free_pipe:%d\n", 
        pipe->ep.bEndpointAddress));

    channel = (rt_uint32_t)pipe->user_data & 0xFF;    
    USBH_Free_Channel(&USB_OTG_Core, channel);

    rt_free(pipe);

    return RT_EOK;
}
예제 #9
0
void USBPT_Work()
{
	if (USBPT_Has_Dev == 0)
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) != 0)
		{
			USBPT_printf("USBPT Device Connecting \r\n");

			if (USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_in),
					0x80,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
				&&
				USBH_Open_Channel(	&USB_OTG_Core_host,
					&(USBPT_Dev->Control.hc_num_out),
					0x00,
					USBPT_Dev->device_prop.address, // still 0 at this point
					USBPT_Dev->device_prop.speed,
					EP_TYPE_CTRL,
					USBPT_Dev->Control.ep0size) == HC_OK
			) {
				DCD_DevConnect(&USB_OTG_Core_dev);
				USBPT_Has_Dev = 1;
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPT Unable to allocate control EP HC \r\n");
			}
		}
		else
		{
			return;
		}
	}
	else
	{
		if (HCD_IsDeviceConnected(&USB_OTG_Core_host) == 0)
		{
			USBPT_printf("USBPT Device Disconnecting \r\n");
			USBD_DeInit(&USB_OTG_Core_dev);
			DCD_DevDisconnect(&USB_OTG_Core_dev);
			USBPT_Has_Dev = 0;

			for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
			{
				USBH_Free_Channel(&USB_OTG_Core_host, &(USBPTH_Listeners[i].hc));
			}

			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out));
			USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in));
		}
	}

	for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++)
	{
		USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i];
		int8_t hc = USBPTH_Listeners[i].hc;
		if (hc >= 0) // if listener is actually allocated
		{
			USBH_EpDesc_TypeDef* epDesc = pl->epDesc;
			uint8_t epnum = epDesc->bEndpointAddress;
			uint8_t epType = 0;
			USBPT_GeneralInDataLen = epDesc->wMaxPacketSize;

			// try to send read tokens only on even frames
			if (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0) continue;

			dbg_trace();

			// attempt to start the read, check the read type first
			if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
				epType = EP_TYPE_INTR;
				USBH_InterruptReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
				epType = EP_TYPE_BULK;
				USBH_BulkReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
				epType = EP_TYPE_ISOC;
				USBH_IsocReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc);
			}

			// now we wait for a reply, or maybe there isn't one
			USBH_Status status;
			char sent = 0;
			delay_1ms_cnt = 100;
			do
			{
				URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
				if (us == URB_DONE)
				{
					// data was indeed received

					// print it to the serial port for monitoring
					USBPT_printf("USBPT:IN:EP0x%02X:", epnum);
					for (uint16_t c = 0; c < USBPT_GeneralInDataLen; c++) {
						USBPT_printf(" 0x%02X", USBPT_GeneralInData[c]);
					}
					USBPT_printf("\r\n");

					// relay the data to the host
					DCD_EP_Tx(&USB_OTG_Core_dev, epnum, USBPT_GeneralInData, USBPT_GeneralInDataLen);
					sent = 1;
					break;
				}
				else if (us == URB_ERROR) {
					dbg_printf(DBGMODE_ERR, "DataIn Error on EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_STALL) {
					dbg_printf(DBGMODE_ERR, "DataIn Stalled EP 0x%02X \r\n", epnum);
					break;
				}
				else if (us == URB_NOTREADY) {
					// NAK, no data
					break;
				}
			}
			while (delay_1ms_cnt > 0);

			if (delay_1ms_cnt == 0) {
				dbg_printf(DBGMODE_ERR, "DataIn Read Timed Out EP 0x%02X \r\n", epnum);
			}
		}
	}
}
예제 #10
0
uint8_t USBPTD_DataOut           (void *pcore , uint8_t epnum)
{
	USB_OTG_CORE_HANDLE* pcore_ = (USB_OTG_CORE_HANDLE*)pcore;
	DCD_DEV* pdev = &(pcore_->dev);
	uint8_t* data;
	uint16_t wLength;

	if (epnum == 0x00)
	{ // CTRL REQ
		wLength = USBPT_CtrlDataLen;
		data = USBPT_CtrlData;
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;
	}

	// print to monitor
	USBPT_printf("USBPT:OUT:EP0x%02X:", epnum);
	for (uint16_t i = 0; i < wLength; i++) {
		USBPT_printf(" 0x%02X", data[i]);
	}
	USBPT_printf("\r\n");

	if (epnum == 0x00)
	{ // CTRL REQ

		USBH_Status status;
		delay_1ms_cnt = 100;

		// wait for transfer complete
		do
		{
			status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen );
			if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
				break;
			}
			else
			{
				status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev);
				if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) {
					break;
				}
			}
		}
		while (delay_1ms_cnt > 0);

		if (delay_1ms_cnt == 0) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut timed out while sending to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else if (status != USBH_OK) {
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut failed to send to device, status: 0x%04X \r\n", status);
			USBD_CtlError(pcore , 0);
			return USBD_FAIL;
		}
		else { // everything is OK
			USBD_CtlSendStatus(pcore);
			return USBD_OK;
		}
	}
	else
	{
		wLength = pdev->out_ep[epnum].xfer_count;
		data = pdev->out_ep[epnum].xfer_buff;

		// allocate memory needed
		if (USBPT_GeneralOutData != 0) free(USBPT_GeneralOutData);
		USBPT_GeneralOutDataLen = wLength;
		USBPT_GeneralOutData = malloc(wLength);
		memcpy(USBPT_GeneralOutData, data, USBPT_GeneralOutDataLen);

		USBH_EpDesc_TypeDef* epDesc = 0;
		for (uint8_t i = 0; i < USBPTH_OutEPCnt; i++)
		{
			// look for appropriate EP
			if (USBPTH_OutEP[i]->bEndpointAddress == epnum) {
				epDesc = USBPTH_OutEP[i];
				break;
			}
		}

		if (epDesc != 0) // EP found
		{
			uint8_t epType = 0;
			int8_t hc = -1;
			if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) {
				epType = EP_TYPE_INTR;
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) {
				epType = EP_TYPE_BULK;
			}
			else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) {
				epType = EP_TYPE_ISOC;
			}

			// dynamically allocate host channel for use
			if (USBH_Open_Channel(	&USB_OTG_Core_host,
									&hc,
									epnum,
									USBPT_Dev->device_prop.address,
									USBPT_Dev->device_prop.speed,
									epType,
									epDesc->wMaxPacketSize) == HC_OK)
			{

				// try to only send on even frame
				volatile uint32_t syncTries = 0x7FFFFFFF;
				while (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0 && syncTries--) __NOP();

				// send using appropriate method
				switch (epType)
				{
					case EP_TYPE_INTR:
						USBH_InterruptSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_BULK:
						USBH_BulkSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					case EP_TYPE_ISOC:
						USBH_IsocSendData(&USB_OTG_Core_host, USBPT_GeneralOutData, USBPT_GeneralOutDataLen, hc);
						break;
					default:
						break;
				}

				// wait until done sending
				USBH_Status status;
				delay_1ms_cnt = 100;
				do
				{
					URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc);
					if (us == URB_DONE) {
						break;
					}
					else if (us == URB_ERROR) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Error on EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
					else if (us == URB_STALL) {
						dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Stalled EP 0x%02X \r\n", epnum);
						DCD_EP_Stall(pcore, epnum);
						break;
					}
				}
				while (delay_1ms_cnt > 0);

				if (delay_1ms_cnt == 0) {
					dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Send Timed Out EP 0x%02X \r\n", epnum);
				}

				// free the channel to be used by something else later
				USBH_Free_Channel(&USB_OTG_Core_host, &hc);
			}
			else
			{
				dbg_printf(DBGMODE_ERR, "USBPTD_DataOut Failed to Alloc HC for EP 0x%02X \r\n", epnum);
			}

		}
		else
		{
			dbg_printf(DBGMODE_ERR, "USBPTD_DataOut No Such EP 0x%02X \r\n", epnum);
		}

		return USBD_OK;
	}

	return USBD_OK;
}
예제 #11
0
/*
 * This is broken. We need to enumerate differently.
 * It causes major problems with several devices if detected in an unexpected order.
 *
 *
 * Oleg - I wouldn't do anything before the newly connected device is considered sane.
 * i.e.(delays are not indicated for brevity):
 * 1. reset
 * 2. GetDevDescr();
 * 3a. If ACK, continue with allocating address, addressing, etc.
 * 3b. Else reset again, count resets, stop at some number (5?).
 * 4. When max.number of resets is reached, toggle power/fail
 * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
 * it doesn't need to be reset again
 * New steps proposal:
 * 1: get address pool instance. exit on fail
 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
 * 3: bus reset, 100ms delay
 * 4: set address
 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
 * 6: while (configurations) {
 *              for(each configuration) {
 *                      for (each driver) {
 *                              6a: Ask device if it likes configuration. Returns 0 on OK.
 *                                      If successful, the driver configured device.
 *                                      The driver now owns the endpoints, and takes over managing them.
 *                                      The following will need codes:
 *                                          Everything went well, instance consumed, exit with success.
 *                                          Instance already in use, ignore it, try next driver.
 *                                          Not a supported device, ignore it, try next driver.
 *                                          Not a supported configuration for this device, ignore it, try next driver.
 *                                          Could not configure device, fatal, exit with fail.
 *                      }
 *              }
 *    }
 * 7: for(each driver) {
 *      7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
 * 8: if we get here, no driver likes the device plugged in, so exit failure.
 *
 */
uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
        //uint8_t bAddress = 0;
        //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
        uint8_t devConfigIndex;
        uint8_t rcode = 0;
        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;
        EpInfo epInfo;
        USB_OTG_CORE_HANDLE *pdev = coreConfig;

        epInfo.epAddr = 0;
        epInfo.maxPktSize = 8;
        epInfo.epAttribs = 0;
        epInfo.bmNakPower = USB_NAK_MAX_POWER;
		// assume:
		// HC0 for control - out
        // HC1 for control - in
        //uint8_t hcnum = USBH_GetFreeChannel(pdev);
        //if(hcnum > 1) {
        //	USBH_Free_Channel(pdev, epInfo.hcNumOut);
        //	USBH_Free_Channel(pdev, epInfo.hcNumIn);
        //}
        USBH_Free_Channel(pdev, 0);
        USBH_Free_Channel(pdev, 1);
		epInfo.hcNumOut = USBH_Alloc_Channel(pdev, 0x00);	// ep_addr = 0
		epInfo.hcNumIn = USBH_Alloc_Channel(pdev, 0x80);
		USBH_Open_Channel(pdev, epInfo.hcNumOut, 0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8);
		USBH_Open_Channel(pdev, epInfo.hcNumIn,	0x0, (lowspeed)?bmLOWSPEED:bmFULLSPEED, EP_TYPE_CTRL, 0x8);
		printf("\nControl Pipe: out = %d (0), in = %d (1)", epInfo.hcNumOut, epInfo.hcNumIn);

        delay_ms(1000);
        AddressPool &addrPool = GetAddressPool();
        // Get pointer to pseudo device with address 0 assigned
        p = addrPool.GetUsbDevicePtr(0);
        if (!p) {
			printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
			return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        // Save old pointer to EP_RECORD of address 0
//        oldep_ptr = p->epinfo;

        // Temporary assign new pointer to epInfo to p->epinfo in order to
        // avoid toggle inconsistence

        p->epinfo = &epInfo;

        p->lowspeed = lowspeed;

        // Get device descriptor
        rcode = getDevDescr(0, 0, 8, (uint8_t*)buf);	// 8 should be enough, sizeof (USB_DEVICE_DESCRIPTOR)
        printf("\nControl - Got 1st 8 bytes desc");

        // Extract Max Packet Size from the device descriptor
        epInfo.maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
        //USB::USBH_Modify_Channel (pdev, epInfo.hcNumOut, 0, 0, 0, 0, epInfo.maxPktSize);
        //USB::USBH_Modify_Channel (pdev, epInfo.hcNumIn, 0, 0, 0, 0, epInfo.maxPktSize);

        // Restore p->epinfo
//         keep CtrlXfer's hcNumOut/In in p->epinfo. p->epinfo = oldep_ptr;

        if (rcode) {
            printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
            return rcode;
        }

        // to-do?
        // Allocate new address according to device class
        //bAddress = addrPool.AllocAddress(parent, false, port);

        //if (!bAddress)
        //        return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
        rcode = getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
        printf("\nControl - Got 2nd 18 bytes desc.");

        uint16_t vid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
        uint16_t pid = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
        uint8_t klass = ((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass;

        // Attempt to configure if VID/PID or device class matches with a driver
        for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if (!devConfig[devConfigIndex]) continue; // no driver
                if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                if (devConfig[devConfigIndex]->VIDPIDOK(vid, pid)) {
					rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
					break;
                } else if (devConfig[devConfigIndex]->DEVCLASSOK(klass)) {
					rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
					if (!rcode) break;
                }
        }

        if (devConfigIndex < USB_NUMDEVICES) {
                return rcode;
        }


        // blindly attempt to configure
        for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
                if (!devConfig[devConfigIndex]) continue;
                if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
                rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);

                //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
                if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
                        // in case of an error dev_index should be reset to 0
                        //		in order to start from the very beginning the
                        //		next time the program gets here
                        //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
                        //        devConfigIndex = 0;
                        return rcode;
                }
        }
        // if we get here that means that the device class is not supported by any of registered classes
        rcode = DefaultAddressing(parent, port, lowspeed);

        return rcode;
}
예제 #12
0
/* USB main task. Performs enumeration/cleanup */
void USB::Task(USB_OTG_CORE_HANDLE *pdev) //USB state machine
{
	uint8_t rcode;
	uint8_t tmpdata;
	static unsigned long delay = 0;
	bool lowspeed = false;

	STM32F2::Task();

	tmpdata = getVbusState();

	/* modify USB task state if Vbus changed */
	switch (tmpdata) {
		case SE1: //illegal state
			usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
			lowspeed = false;
			break;
		case SE0: //disconnected
			if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
					usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
			lowspeed = false;
			break;
		case LSHOST:
//        if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
			lowspeed = true;
//        }
		case FSHOST: //attached
			if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
				delay = millis() + USB_SETTLE_DELAY;
				usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
				STM_EVAL_LEDToggle(LED1);
			}
			break;
	}// switch( tmpdata

	for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
		if (devConfig[i])
			rcode = devConfig[i]->Poll();

	switch (usb_task_state) {
		case USB_DETACHED_SUBSTATE_INITIALIZE:
				init();

				for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
					if (devConfig[i])
							rcode = devConfig[i]->Release();

				usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
				break;
		case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
				break;
		case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
				break;
		case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
			if (delay < millis())
				usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
			break;
		case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
			STM_EVAL_LEDToggle(LED1);
			//regWr(rHCTL, bmBUSRST); //issue bus reset
			// what if i want to reset the specified device? (need to survey usb hub feature later)
			pdev->host.SofHits = 0;
			HCD_ResetPort();

			//usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
			// the HCD_ResetPort() function will take care of a complete bus reset. so skip next phase.
			usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
			break;
/*			case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
				if ((regRd(rHCTL) & bmBUSRST) == 0) {
						tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
						regWr(rMODE, tmpdata);
						usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
						//delay = millis() + 20; //20ms wait after reset per USB spec
				}
				break;*/

		case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
			if(pdev->host.port_need_reset) {
				usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
				pdev->host.port_need_reset = 0;
				printf("\nLS Dev, reset again");
				break;
			}
			STM_EVAL_LEDToggle(LED1);

			//if (regRd(rHIRQ) & bmFRAMEIRQ) {
			if(pdev->host.SofHits) {
				//when first SOF received _and_ 20ms has passed we can continue
				usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
				delay = millis() + 20;
			}
			break;
		case USB_ATTACHED_SUBSTATE_WAIT_RESET:
			if (delay < millis()) {
				usb_task_state = USB_STATE_CONFIGURING;
			}
			break;
		case USB_STATE_CONFIGURING:
			STM_EVAL_LEDToggle(LED1);
					//Serial.print("\r\nConf.LS: ");
					//Serial.println(lowspeed, HEX);
			printf("\nTODO:Support all 8 USB pipe?");
			rcode = Configuring(0, 0, lowspeed);

			if (rcode) {
				if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
					usb_error = rcode;
					usb_task_state = USB_STATE_ERROR;
				}
			} else
				usb_task_state = USB_STATE_RUNNING;
			break;
		case USB_STATE_RUNNING:
			break;
		case USB_STATE_ERROR:
				//MAX3421E::Init();
	        AddressPool &addrPool = GetAddressPool();
	        // Get pointer to pseudo device with address 0 assigned
	        UsbDevice *p = addrPool.GetUsbDevicePtr(0);

			USBH_Free_Channel(pdev, p->epinfo->hcNumOut);
			USBH_Free_Channel(pdev, p->epinfo->hcNumIn);
			break;
	} // switch( usb_task_state )
}
/**
  * @brief  This function send data to the device.
  * @param  fileName : name of the file 
  * @retval the filestate will be returned 
  * FS_SUCCESS : returned to the parent function when the file length become to zero
  */
void  CDC_StopReception( USB_OTG_CORE_HANDLE *pdev)
{
  RX_Enabled = 0; 
  USB_OTG_HC_Halt(pdev, CDC_Machine.CDC_DataItf.hc_num_in);
  USBH_Free_Channel  (pdev,CDC_Machine.CDC_DataItf.hc_num_in);
}