2012-05-26 03:32 PM
Hello,
I'm working with STM32 since some weeks now and I'd like to use the Custom-Hid code from the STM32_USB-FS-Device_Lib_V3.3.0 for one of my projects based on STM32L151. In contrary to the Custom-Hid example I'd like to use feature reports in addition to the input and output reports. In the example code feature reports are also defined, but I was not able to work with them. I don't understand if, where and how they are processed with the given code. The host will work with HidD_GetFeature/HidD_SetFeature, but what about the device? It would be great if someone had an idea that could help me. Best regards and thanks in advance, Michael #custom-usb-hid-device2012-06-18 08:38 PM
Duplicate Post...sorry
2012-06-19 02:51 AM
> What is causing the CustomHID_GetReport_Feature() or CustomHID_SetReport_Feature() to be called in the data stage?
CustomHID_Data_Setup() registers the user callback, CustomHID_GetReport_Feature() or CustomHID_SetReport_Feature(), to pInformation->Ctrl_Info.CopyDataRESULT CustomHID_Data_Setup(uint8_t RequestNo)
{ ... ... /*** GET_REPORT ***/ else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == GET_REPORT) { CopyRoutine = Joystick_GetReportValue; }/*** SET_REPORT ***/
else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == SET_REPORT) { CopyRoutine = Joystick_SetReportValue; } ... ... pInformation->Ctrl_Info.CopyData = CopyRoutine; // <--- register user callback to stack return USB_SUCCESS; } For Control write transfer, the stack calls ''CopyData'' function pointer at DataStageOut()\STM32_USB-FS-Device_Lib_V3.3.0\Libraries\STM32_USB-FS-Device_Driver\src\usb_core.c
void DataStageOut(void) { ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; uint32_t save_rLength;save_rLength = pEPinfo->Usb_rLength;
if (pEPinfo->CopyData && save_rLength)
{ uint8_t *Buffer; uint32_t Length;Length = pEPinfo->PacketSize;
if (Length > save_rLength) { Length = save_rLength; }Buffer = (*pEPinfo->CopyData)(Length); // <--- user callback is called to get a buffer address
pEPinfo->Usb_rLength -= Length; pEPinfo->Usb_rOffset += Length; // <--- stack copies data from EP to the buffer #ifdef STM32F10X_CL PCD_EP_Read(ENDP0, Buffer, Length); #else PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); #endif /* STM32F10X_CL */ } ... As you see, the buffer is filled after user callback is called. Therefore, we have to get another chance at CustomHID_Status_In(), to process data on the buffer. As of Control Read transfer, the user callback is called from DataStageIn()\STM32_USB-FS-Device_Lib_V3.3.0\Libraries\STM32_USB-FS-Device_Driver\src\usb_core.c
void DataStageIn(void) { ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; uint32_t save_wLength = pEPinfo->Usb_wLength; uint32_t ControlState = pInformation->ControlState;uint8_t *DataBuffer;
uint32_t Length; ... ... Length = pEPinfo->PacketSize; ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;if (Length > save_wLength)
{ Length = save_wLength; }DataBuffer = (*pEPinfo->CopyData)(Length); // <--- user callback is called to get the buffer address
// <--- Copy data from the buffer to EP #ifdef STM32F10X_CL PCD_EP_Write (ENDP0, DataBuffer, Length); #else UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); #endif /* STM32F10X_CL */ ... Anyway, this implementation is too redundant, as usual of ST. My recommendation is, 1) At SETUP stage, the stack calls user_SETUP_handler() (combined CustomHID_Data_Setup() and CustomHID_Data_Setup()) 2) user_SETUP_handler() interprets the SETUP packet, to know the request. If it doesn't accept the request, this routines returns FALSE. 3-1) For No-data Control transfer, user_SETUP_handler() process the requests and returns TRUE 3-2) For Control Read transfer, user_SETUP_handler() fills a buffer with requested data. And it passes the buffer address and data size over stack parameters. And then, it returns TRUE 3-3) For Control Write transfer, user_SETUP_handler() passes a buffer (greater than wLength) and a function pointer of user callback to the stack. And it returns TRUE. The stack calls this user callback at STATUS stage. The stack processes the rest of all :) Tsuneo2012-06-25 05:26 PM
Tsuneo,
Thanks for all the information. What I didnt realize was that the desired routine is called twice. Once with the call (*CopyRoutine)(0); And then later by the stack using the length parameter to designate which stage its in. Gary2012-06-25 09:14 PM
So I am still learning how the STM stack is working. I come from a background of using LUFA USB stack for AVRs and the Microchip USB Stack for PIC processors.
So I simple did the following in my routine and see the Set Report Data uint8_t *Joystick_SetReportValue(uint16_t Length) { uint8_t mybuff[64]; uint32_t numread = 0; if (Length == 0) {pInformation->Ctrl_Info.Usb_wLength = 1;
return NULL; } else { numread = USB_SIL_Read(EP0_OUT, mybuff); } return USB_SUCCESS; } Question is to what I should set as the length (highlighted in green above). It seems to be ok as is but may be introducing problems. Thanks again for all the help. Gary2012-06-26 09:42 PM
Hi Gary,
Your code is modified as follows, Tsuneouint8_t Request = 0; // completed request at status stage
uint8_t mybuff[64]; // this buffer must be global RESULT Joystick_Data_Setup(uint8_t RequestNo) { ... ... /*** SET_REPORT ***/ else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == SET_REPORT) { CopyRoutine = Joystick_SetReportValue; Request = SET_REPORT; // <------- add this line to here } ... ... uint8_t *Joystick_SetReportValue(uint16_t Length) { if (Length == 0) { pInformation->Ctrl_Info.Usb_wLength = 1; return NULL; } else { return mybuff; } } void Joystick_Status_In(void) { if (Request == SET_REPORT) // SET_REPORT completion { Request = 0; // // now, stack has filled mybuff[] // pInformation->USBwLengths.w holds transferred size // process it // } }2013-03-01 01:28 AM
Hi Guys,
I have a custom device that has some memory and a micro-controller. Due to cost implications the device cannot have its own USB interface. To access the memory and the micro controller status I use a custom made USB dongle that converts USB commands into SPI commands (I communicate with the memory and micro by means of SPI). The USB dongle has a STM32L151. I've done a HID implementation using Delphi (HIDKomponente). The memory device is 512kb and on some PC's I can read the entire in 13seconds and write the entire device in 30seconds but then on other PC it will take 58seconds and 300seconds respectively. The code is at the a point where the speed can't be increased anymore (reduced HID polling interval to 1ms) but 300seconds is WAY TOO LONG and I need an alternative. As always, I'm trying to do this without having to install USB drivers and do it as fast as possible. But with the inherent delays of HID I do not think I'm going to get the speed I want. I've been considering maybe using mass storage class. With this I should get quite high transfer rates and again I wont need any drivers. This will work fine fro programming the memory but what about the micro status. Will I be able to read the micro status using mass storage? If you guys can propose any other USB class with high transfer rates that does not require drivers and can do what I've described above. Thank you2013-03-01 09:01 AM
> If you guys can propose any other USB class with high transfer rates that does not require drivers and can do what I've described above.
Generic Text-Only printer Visit to this post on Keil forum for the details. http://www.keil.com/forum/21682/ .NET Framework System.Printing.PrintQueue makes the host code simple. See the example on this MSDN page. http://msdn.microsoft.com/en-us/library/ms552912(v=vs.90).aspx You may read out from printer's JobStream, too. Tsuneo2013-03-02 09:54 PM
That looks nice. I don't use .NET, I use Delphi. Can I use Delphi printer? or maybe libusb?
Libusb supports bulk interfaces.2013-03-03 09:01 AM
> I don't use .NET, I use Delphi.
Delphi has supported .NET Framework since Delphi8. But Embarcadero made .NET support as an option of prism, not for XE3.> Can I use Delphi printer? Maybe, but I'm not sure. You may code it using just Win32 API HOWTO: Send Raw Data to a Printer by Using the Win32 API http://support.microsoft.com/kb/138594/en-us> maybe libusb? If libusb-Win32 would be acceptable for you, any USB class, including vendor-specific, will do ;) libusb-Win32 isn't an in-box driver. Tsuneo2015-08-21 01:17 PM
Hi Tsuneo,
did you already extend the Cube framework to also support GetFeature reports and if yes, could you write down the neccessary changes? SetFeature seems to be implemented and working out of the box. Best regards, Michael