Author Topic: interrupt INs and OUTs in Microchip  (Read 14884 times)

mdlayt

  • Member
  • ***
  • Posts: 40
interrupt INs and OUTs in Microchip
« on: December 09, 2010, 04:03:23 pm »
Jan,

Great site!
 
We have successfully used your sample design and derived devices that do INs and OUTs and are able to connect with the generic HID driver:
   pic_usb_device_hid_generic_10.zip
   Generic_HID Firmware for Microchip 18F USB Chips
   Using Microchip MCHPFSUSB Framework v2.5a
 

I'm trying to create a similar device in a CY7C64343 and I can't get OUTs to work.
 
The thing that doesn't make sense to me, in your Microchip code, it appears to use Endpoint 1 for both IN and OUT, which I didn't think was possible.
   #define HID_EP                  1
 
   void USBCBInitEP(void)
   {
       //enable the HID endpoint
       USBEnableEndpoint(HID_EP,
 
   /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,        //Endpoint Descriptor
    HID_EP | _EP_IN,                //EndpointAddress
    _INTERRUPT,                     //Attributes
    0x40,0x00,                      //size
    0x01,                           //Interval
 
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,        //Endpoint Descriptor
    HID_EP | _EP_OUT,               //EndpointAddress
    _INTERRUPT,                     //Attributes
    0x40,0x00,                      //size
    0x01                            //Interval
 

What I expect to see is something more like in your EZUSB HID, where Endpoints 1 and 2 are used.

EpO2Dscr:
        db  EpO2DscrEnd-EpO2Dscr        ;; Descriptor length
        db  DSCR_ENDPNT ;; Descriptor type
        db  00000010b   ;; Endpoint number, and direction
        db  ET_INT      ;; Endpoint type
        db  40H     ;; Maximun packet size (LSB)
        db  00H     ;; Max packect size (MSB)
        db  100     ;; Polling interval
EpO2DscrEnd:
 
EpI1Dscr:
        db  EpI1DscrEnd-EpI1Dscr        ;; Descriptor length
        db  DSCR_ENDPNT ;; Descriptor type
        db  10000001b   ;; Endpoint number, and direction
        db  ET_INT      ;; Endpoint type
        db  40H     ;; Maximun packet size (LSB)
        db  00H     ;; Max packect size (MSB)
        db  100     ;; Polling interval
EpI1DscrEnd:
 

Is there something magic that makes this work in the Microchip?
 
Thanks,
Mike

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: interrupt INs and OUTs in Microchip
« Reply #1 on: December 09, 2010, 04:31:25 pm »
All of the endpoint numbers except zero can support two endpoint addresses; endpoint 1 IN and endpoint 1 OUT, etc. Whether they do so can vary with the hardware, but most of the hardware I've seen, including Microchip's, supports both directions for the supported endpoint numbers.

For HIDs, one thing to remember is that if the descriptors don't specify an interrupt OUT endpoint, the host will use control transfers for Output reports. So you could look to see if the host is recognizing your interrupt OUT endpoint or attempting control transfers instead.

If you can find example code for bulk Out transfers, interrupt OUT transfers are identical on the device. The only difference is in the endpoint descriptors and the scheduling on the host.

Jan

mdlayt

  • Member
  • ***
  • Posts: 40
Re: interrupt INs and OUTs in Microchip
« Reply #2 on: December 09, 2010, 05:11:48 pm »
OK.  I'm not sure I'm any less confused, but I am more enlightened.

So I went back to the USB 2.0 spec 5.3.1 and I see "The combination of the device address, endpoint number, and direction allows each endpoint to be uniquely referenced."

I was not aware until now that an endpoint has a number, and also an address which is independent of the number.  I infer that the purpose of the address being independent is to confuse people.

In any case, I guess I have to keep in mind that in any particular code, when I see an integer associated with an endpoint, it might be the number or the address.  And hope that the coder knew which--not to mention the USB designers.

 ...

I'm pretty sure that I'm connecting to the HID driver in a way that it thinks I have an OUT, because HidP_GetCaps returns that m_HIDCapabilities includes an OutputReportByteLength of 0x0041, which is what I'm asking for (64 plus the ID which appears on the host side).

I just can't gets OUTs to work.  And I don't see any code for CY7C64343 that has any that do.  I guess I will try to see what Cypress has to say.  I have two outstanding requests, so I might as well add another one. ;)

Thanks,
Mike

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: interrupt INs and OUTs in Microchip
« Reply #3 on: December 09, 2010, 05:21:14 pm »
Some of the terminology in the USB spec is confusing. Endpoint number/endpoint address is one example. Also transaction/transfer.

HidP_GetCaps will tell you about the reports but not whether the host will use the control endpoint or an interrupt endpoint to send them.

The interrupt OUT endpoint must of course be enabled and armed to ACK the data when it arrives. A protocol analyzer would show if the data is going out on the bus.

What happens at the host application after WriteFile (assuming Windows)?

Jan

mdlayt

  • Member
  • ***
  • Posts: 40
Re: interrupt INs and OUTs in Microchip
« Reply #4 on: December 09, 2010, 06:06:13 pm »
I think I have something working now.

I thought the first WriteFile() was just returning FAIL, but maybe it was actually the second one that failed.  I think the thing I was missing was the call to reenable after the OUT.  This code is working (but probably needs a timeout waiting for the IN to be safe).

    static unsigned char EPEnabled = FALSE;

    if (USB_bGetConfiguration() == 0) {    // Wait for USB enumeration
        return;
    }

    if (!EPEnabled) {
        USB_EnableOutEP(2);
        EPEnabled = TRUE;
    }

    if (USB_bGetEPState(2) == EVENT_PENDING) {

        USB_bReadOutEP(2, &USBBufOut[0], 64);

        USBBufIn[0] = hostSync | PACKET_DEBUG;
        USBBufIn[1] = 0x02;
        USBBufIn[2] = USBBufOut[0];
        USBBufIn[3] = USBBufOut[1];

        while (USB_bGetEPState(1) != IN_BUFFER_EMPTY) {}

        USB_LoadInEP(1, &USBBufIn[0], 64, USB_TOGGLE);

        USB_EnableOutEP(2);
    }


Another thing I noticed is that the host side connection sequence is magic (I think what I have is derived from you host side HID app).  I'm pretty sure I have seen some code somewhere that calls CreateFile only once with both GENERIC_READ and GENERIC_WRITE and gets one handle to use for both reads and writes.  I tried that and it didn't work at all.  Also, I read somewhere that the CreateFile call automatically connects to the highest Endpoint "Pipe" with the matching direction on the device.  I wonder if it means the highest number or highest address.  God only knows.
                    m_WriteHandle = CreateFile( m_pInterfaceDetails->Devi
                                                GENERIC_WRITE,
                                                FILE_SHARE_READ|FILE_SHAR
                                                (LPSECURITY_ATTRIBUTES)NU
                                                OPEN_EXISTING,
                                                0,
                                                NULL );

                    m_ReadHandle = CreateFile( m_pInterfaceDetails->Devic
                                               GENERIC_READ,
                                               FILE_SHARE_READ|FILE_SHARE
                                               (LPSECURITY_ATTRIBUTES)NUL
                                               OPEN_EXISTING,
                                               FILE_FLAG_OVERLAPPED,
                                               NULL);


Thanks again,
Mike