/** * Sets the active setting of the given interface if the configuration supports * it; otherwise, the control pipe is STALLed. If the setting of an interface * changes. * \parma pDriver Pointer to a USBDDriver instance. * \parma infnum Interface number. * \parma setting New active setting for the interface. */ static void SetInterface( USBDDriver *pDriver, uint8_t infnum, uint8_t setting) { /* Make sure alternate settings are supported */ if (!pDriver->pInterfaces) { USBD_Stall(0); } else { /* Change the current setting of the interface and trigger the callback */ /* if necessary */ if (pDriver->pInterfaces[infnum] != setting) { pDriver->pInterfaces[infnum] = setting; USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting); } /* Acknowledge the request */ USBD_Write(0, 0, 0, 0, 0); } }
/**************************************************************************//** * @brief * Start a USB bulk-in transfer to send a CSW back to host. *****************************************************************************/ __STATIC_INLINE void SendCsw(void) { if ( ledPort != -1 ) GPIO_PinOutToggle((GPIO_Port_TypeDef)ledPort, ledPin); USBD_Write(BULK_IN, (void*) &csw, CSW_LEN, NULL); }
//------------------------------------------------------------------------------ /// Sends the current status of the device to the host. /// \param pDriver Pointer to a USBDDriver instance. //------------------------------------------------------------------------------ static void GetDeviceStatus(const USBDDriver *pDriver) { static unsigned short data; const USBConfigurationDescriptor *pConfiguration; data = 0; // Use different configuration depending on device speed if (USBD_IsHighSpeed()) { pConfiguration = pDriver->pDescriptors->pHsConfiguration; } else { pConfiguration = pDriver->pDescriptors->pFsConfiguration; } // Check current configuration for power mode (if device is configured) if (pDriver->cfgnum != 0) { if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) { data |= 1; } } // Check if remote wake-up is enabled if (pDriver->isRemoteWakeUpEnabled) { data |= 2; } // Send the device status USBD_Write(0, &data, 2, 0, 0); }
inline uint16_t usb_send(const void *data, const uint16_t length) { if((send_status & (USB_IN_FUNCTION))) { return 0; } if(!(send_status & USB_CALLBACK)) { send_status |= USB_IN_FUNCTION; if(USBD_Write(IN_EP, data, length, usb_send_callback, 0) != USBD_STATUS_SUCCESS) { send_status &= ~USB_IN_FUNCTION; return 0; } } else { return 0; } uint16_t num_tries = 0; while(~send_status & USB_CALLBACK) { taskYIELD(); num_tries++; // USBD_Write does not always call callback when USBD_STATUS_SUCCESS // Wait for NUM_SEND_TRIES if(num_tries > NUM_SEND_TRIES) { send_status = 0; return 0; } } send_status = 0; return usb_send_transferred; }
//------------------------------------------------------------------------------ /// Configures the device by setting it into the Configured state and /// initializing all endpoints. /// \param pDriver Pointer to a USBDDriver instance. /// \param cfgnum Configuration number to set. //------------------------------------------------------------------------------ static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum) { USBEndpointDescriptor *pEndpoints[BOARD_USB_NUMENDPOINTS+1]; const USBConfigurationDescriptor *pConfiguration; pConfiguration = pDriver->pDescriptors->pFsConfiguration; // Set & save the desired configuration USBD_SetConfiguration(cfgnum); pDriver->cfgnum = cfgnum; // If the configuration is not 0, configure endpoints if (cfgnum != 0) { // Parse configuration to get endpoint descriptors USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0); // Configure endpoints int i = 0; while (pEndpoints[i] != 0) { USBD_ConfigureEndpoint(pEndpoints[i]); i++; } } // Should be done before send the ZLP USBDDriverCallbacks_ConfigurationChanged(cfgnum); // Acknowledge the request USBD_Write(0, // Endpoint #0 0, // No data buffer 0, // No data buffer (TransferCallback) 0, (void *) 0); }
/********************************************************** * Interrupt handler for push button 1 **********************************************************/ void GPIO_EVEN_IRQHandler(void) { /* Clear the interrupt flag */ GPIO->IFC = 1 << 10; /* Send message */ USBD_Write(EP_IN, button1message, sizeof(button1message), dataSentCallback); }
/** Write data to a USB host. @param buffer The data to send. @param length How many bytes to send. @return The number of bytes successfully written. \b Example \code UsbSerial* usb = UsbSerial::get(); // get a reference to the usb system int written = usb->write( "hi hi", 5 ); \endcode */ int UsbSerial::write( const char *buffer, int length ) { int rv = 0; if( USBD_GetState() == USBD_STATE_CONFIGURED ) { if( USBD_Write(CDCDSerialDriverDescriptors_DATAIN, buffer, length, 0, 0) == USBD_STATUS_SUCCESS ) rv = length; } return rv; }
/** * Callback function when SetReport request data received from host * \param pArg Pointer to additional argument struct * \param status Result status * \param transferred Number of bytes transferred * \param remaining Number of bytes that are not transferred yet */ static void HIDDTransferDriver_ReportReceived(void *pArg, uint8_t status, uint32_t transferred, uint32_t remaining) { HIDDTransferDriver *pDrv = &hiddTransferDriver; pDrv->iReportLen = transferred; USBD_Write(0, 0, 0, 0, 0); }
static void fastsource_get_feat_cur_val(uint8_t entity, uint8_t channel, uint8_t control, uint8_t length) { TRACE_INFO("get_feat(E%u, CN%u, CS%u, L%u) ", entity, channel, control, length); if (channel == 0 && control == AUDFeatureUnitDescriptor_MUTE && length == 1) USBD_Write(0, &usb_state.muted, sizeof(usb_state.muted), 0, 0); else USBD_Stall(0); }
static int firmware_get(const USB_Setup_TypeDef *setup) { int res = USB_STATUS_REQ_ERR; CHECK_SETUP_IN(USBTHING_FIRMWARE_MAX_SIZE); res = USBD_Write(0, firmware_version, sizeof(firmware_version), NULL); return res; }
//------------------------------------------------------------------------------ /// Sends the current line coding information to the host through Control /// endpoint 0. //------------------------------------------------------------------------------ static void CDCDSerialDriver_GetLineCoding(void) { TRACE_INFO_WP("gLineCoding "); USBD_Write(0, (void *) &(cdcdSerialDriver.lineCoding), sizeof(CDCLineCoding), 0, 0); }
/** * Sends the current line coding information to the host through Control * endpoint 0. * \param pCdcd Pointer to CDCDSerialPort instance. */ static void _GetLineCoding(CDCDSerialPort * pCdcd) { TRACE_INFO_WP("gLineCoding "); USBD_Write(0, (void *) &(pCdcd->lineCoding), sizeof(CDCLineCoding), 0, 0); }
//------------------------------------------------------------------------------ /// Sends a data buffer through the virtual COM port created by the CDC /// device serial driver. This function behaves exactly like USBD_Write. /// \param data Pointer to the data buffer to send. /// \param size Size of the data buffer in bytes. /// \param callback Optional callback function to invoke when the transfer /// finishes. /// \param argument Optional argument to the callback function. /// \return USBD_STATUS_SUCCESS if the read operation has been started normally; /// otherwise, the corresponding error code. //------------------------------------------------------------------------------ unsigned char CDCDSerialDriver_Write(void *data, unsigned int size, TransferCallback callback, void *argument) { return USBD_Write(CDCDSerialDriverDescriptors_DATAIN, data, size, callback, argument); }
/** * Sends the current configuration number to the host. * \param pDriver Pointer to a USBDDriver instance. */ static void GetConfiguration(const USBDDriver *pDriver) { unsigned long tmp; // Coud be unsigned char : unsigned long has been chose to avoid any potential alignment issue with DMA if( USBD_GetState() < USBD_STATE_CONFIGURED) tmp = 0; // If device is unconfigured, returned configuration must be 0 else tmp = pDriver->cfgnum; USBD_Write(0, &tmp, 1, 0, 0); }
/** * Send a NULL packet */ static void TerminateCtrlInWithNull(void *pArg, uint8_t status, uint32_t transferred, uint32_t remaining) { USBD_Write(0, /* Endpoint #0 */ 0, /* No data buffer */ 0, /* No data buffer */ (TransferCallback) 0, (void *) 0); }
uint32_t CDCDSerialPort_Write(const CDCDSerialPort * pCdcd, void * pData, uint32_t dwSize, TransferCallback fCallback, void * pArg) { if (pCdcd->bBulkInPIPE == 0) return USBRC_PARAM_ERR; return USBD_Write(pCdcd->bBulkInPIPE, pData, dwSize, fCallback, pArg); }
//------------------------------------------------------------------------------ /// Changes the state of the serial driver according to the information /// sent by the host via a SetControlLineState request, and acknowledges /// the request with a zero-length packet. //------------------------------------------------------------------------------ static void CDCDSerialDriver_SetControlLineState(unsigned char activateCarrier, unsigned char isDTEPresent) { TRACE_INFO_WP( "sControlLineState(%d, %d) ", activateCarrier, isDTEPresent); cdcdSerialDriver.isCarrierActivated = activateCarrier; USBD_Write(0, 0, 0, 0, 0); }
//----------------------------------------------------------------------------- /// Writes to host through MSD defined bulk IN pipe. Act as USBD_Write but by /// a fixed IN endpoint. /// \param data Pointer to the data that writes to the host. /// \param size The number of bytes should be write. /// \param callback Pointer to the function invoked on end of writing. /// \param argument Pointer to additional argument data struct. //----------------------------------------------------------------------------- char MSDD_Write(void *data, unsigned int size, TransferCallback callback, void *argument) { return USBD_Write(MSDDriverDescriptors_BULKIN, data, size, callback, argument); }
//------------------------------------------------------------------------------ /// Send a NULL packet //------------------------------------------------------------------------------ static void TerminateCtrlInWithNull(void *pArg, unsigned char status, unsigned int transferred, unsigned int remaining) { USBD_Write(0, // Endpoint #0 0, // No data buffer 0, // No data buffer (TransferCallback) 0, (void *) 0); }
/**************************************************************************//** * @brief * Start a USB bulk-in or bulk-out transfer to transfer a data payload * to/from host. * * @param[in] data * Pointer to data payload. * * @param[in] len * Number of bytes to transfer. * * @param[in] cb * Transfer completion callback. *****************************************************************************/ static void UsbXferBotData(uint8_t *data, uint32_t len, USB_XferCompleteCb_TypeDef cb) { if (pCmdStatus->direction) { USBD_Write(BULK_IN, data, len, cb); } else { USBD_Read(BULK_OUT, data, len, cb); } }
static int gpio_get(const USB_Setup_TypeDef *setup) { CHECK_SETUP_IN(USBTHING_CMD_GPIO_GET_SIZE); uint8_t pin = setup->wIndex; struct usbthing_ctrl_s *ctrl = (struct usbthing_ctrl_s*)&cmd_buffer; ctrl->gpio_cmd.get.level = GPIO_get(pin); //TODO: respond return USBD_Write(0, cmd_buffer, USBTHING_CMD_GPIO_GET_SIZE, NULL); }
//----------------------------------------------------------------------------- /// Sends the current line coding information to the host through Control /// endpoint 0. /// \param request Pointer to a USBGenericRequest instance. //----------------------------------------------------------------------------- static void CDCD_GetLineCoding(const USBGenericRequest *request) { unsigned char serial; serial = CDCD_GetSerialPort(request); TRACE_INFO_WP("gLineCoding_%d ", serial); USBD_Write(0, (void *) &(cdcFunDriver.pCdcPorts[serial].lineCoding), sizeof(CDCLineCoding), 0, 0); }
//------------------------------------------------------------------------------ /// Callback triggered after the new mute status of a channel has been read /// by AUDDSpeakerDriver_SetFeatureCurrentValue. Changes the mute status /// of the given channel accordingly. /// \param channel Number of the channel whose mute status has changed. //------------------------------------------------------------------------------ static void AUDDSpeakerDriver_MuteReceived(unsigned int channel) { if (muted) { AUDDSpeakerChannel_Mute(&(auddSpeakerDriver.channels[channel])); } else { AUDDSpeakerChannel_Unmute(&(auddSpeakerDriver.channels[channel])); } USBD_Write(0, 0, 0, 0, 0); }
/** * Write data through USB interrupt IN EP. * \param pData Pointer to the data sent. * \param dLength The data length. * \param fCallback Callback function invoked when transferring done. * \param pArg Pointer to additional arguments. */ uint8_t HIDDTransferDriver_Write(const void *pData, uint32_t dLength, TransferCallback fCallback, void *pArg) { HIDDTransferDriver *pDrv = &hiddTransferDriver; if (dLength != HIDDTransferDriver_REPORTSIZE) { dLength = HIDDTransferDriver_REPORTSIZE; } return USBD_Write(pDrv->hidFunction.bPipeIN, pData, dLength, fCallback, pArg); }
/** Write data to a USB host. @param buffer The data to send. @param length How many bytes to send. @return The number of bytes successfully written. \b Example \code int written = UsbSerial_write( "hi hi", 5 ); \endcode */ int UsbSerial_write( const char *buffer, int length, int timeout ) { int rv = 0; if( USBD_GetState() == USBD_STATE_CONFIGURED ) { if( USBD_Write(CDCDSerialDriverDescriptors_DATAIN, buffer, length, UsbSerial_onUsbWritten, 0) == USBD_STATUS_SUCCESS ) { if( SemaphoreTake( usbSerial.writeSemaphore, timeout ) ) { rv = usbSerial.justWrote; usbSerial.justWrote = 0; } } } return rv; }
//------------------------------------------------------------------------------ /// Sends the currently active setting of the given interface to the USB /// host. If alternate settings are not supported, this function STALLs the /// control pipe. /// \param pDriver Pointer to a USBDDriver instance. /// \param infnum Interface number. //------------------------------------------------------------------------------ static void GetInterface( const USBDDriver *pDriver, unsigned char infnum) { // Make sure alternate settings are supported, or STALL the control pipe if (!pDriver->pInterfaces) { USBD_Stall(0); } else { // Sends the current interface setting to the host USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0); } }
/** * Configures the device by setting it into the Configured state and * initializing all endpoints. * \param pDriver Pointer to a USBDDriver instance. * \param cfgnum Configuration number to set. */ static void SetConfiguration(USBDDriver *pDriver, uint8_t cfgnum) { USBEndpointDescriptor *pEndpoints[17]; const USBConfigurationDescriptor *pConfiguration; /* Use different descriptor depending on device speed */ if ( USBD_HAL_IsHighSpeed() && pDriver->pDescriptors->pHsConfiguration) { pConfiguration = pDriver->pDescriptors->pHsConfiguration; } else { pConfiguration = pDriver->pDescriptors->pFsConfiguration; } /* Set & save the desired configuration */ USBD_SetConfiguration(cfgnum); pDriver->cfgnum = cfgnum; pDriver->isRemoteWakeUpEnabled = ((pConfiguration->bmAttributes & 0x20) > 0); /* If the configuration is not 0, configure endpoints */ if (cfgnum != 0) { /* Parse configuration to get endpoint descriptors */ USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0); /* Configure endpoints */ int i = 0; while (pEndpoints[i] != 0) { USBD_ConfigureEndpoint(pEndpoints[i]); i++; } } /* Should be done before send the ZLP */ if (NULL != USBDDriverCallbacks_ConfigurationChanged) USBDDriverCallbacks_ConfigurationChanged(cfgnum); /* Acknowledge the request */ USBD_Write(0, /* Endpoint #0 */ 0, /* No data buffer */ 0, /* No data buffer */ (TransferCallback) 0, (void *) 0); }
//----------------------------------------------------------------------------- /// Changes the state of the serial driver according to the information /// sent by the host via a SetControlLineState request, and acknowledges /// the request with a zero-length packet. /// \param request Pointer to a USBGenericRequest instance. /// \param activateCarrier The active carrier state to set. /// \param isDTEPresent The DTE status. //----------------------------------------------------------------------------- static void CDCD_SetControlLineState(const USBGenericRequest *request, unsigned char activateCarrier, unsigned char isDTEPresent) { unsigned char serial; serial = CDCD_GetSerialPort(request); TRACE_INFO_WP( "sControlLineState_%d(%d, %d) ", serial, activateCarrier, isDTEPresent); cdcFunDriver.pCdcPorts[serial].isCarrierActivated = activateCarrier; USBD_Write(0, 0, 0, 0, 0); }
//----------------------------------------------------------------------------- /// Sends a data buffer through the virtual COM port created by the CDC /// function serial driver. This function behaves exactly like <USBD_Write>. /// \param port Port index to receive. /// \param data - Pointer to the data buffer to send. /// \param size - Size of the data buffer in bytes. /// \param callback - Optional callback function to invoke when the transfer /// finishes. /// \param argument - Optional argument to the callback function. /// \return <USBD_STATUS_SUCCESS> if the write operation started normally; /// otherwise, the corresponding error code. //----------------------------------------------------------------------------- unsigned char CDCDSerialDriver_Write(unsigned char port, void *data, unsigned int size, TransferCallback callback, void *argument) { unsigned char ep = cdcFunDriver.pCdcPorts[port].bulkInEndpoint; if (port > cdcFunDriver.numPorts) return USBD_STATUS_INVALID_PARAMETER; return USBD_Write(ep, data, size, callback, argument); }
/** * Callback function which should be invoked after the data of a * SetLineCoding request has been retrieved. Sends a zero-length packet * to the host for acknowledging the request. * \param pCdcd Pointer to CDCDSerialPort instance. */ static void _SetLineCodingCallback(CDCDSerialPort * pCdcd) { uint32_t exec = 1; if (pCdcd->fEventHandler) { uint32_t rc = pCdcd->fEventHandler( CDCDSerialPortEvent_SETLINECODING, (uint32_t)(&lineCoding), pCdcd->pArg); if (rc == USBD_STATUS_SUCCESS) { pCdcd->lineCoding.dwDTERate = lineCoding.dwDTERate; pCdcd->lineCoding.bCharFormat = lineCoding.bCharFormat; pCdcd->lineCoding.bParityType = lineCoding.bParityType; pCdcd->lineCoding.bDataBits = lineCoding.bDataBits; } else exec = 0; } if (exec) USBD_Write(0, 0, 0, 0, 0); else USBD_Stall(0); }