Shop OBEX P1 Docs P2 Docs Learn Events
P2 USB Host driver (re-)development thread - Page 10 — Parallax Forums

P2 USB Host driver (re-)development thread

17810121315

Comments

  • And now there's version 1.0.0-rc2, which fixes a regression and allows multi-report devices on the root port to be used as multiple devices.

  • Today's live forum outgrowth: "when you have a 7 port hub and 7 dolls..."

  • roglohrogloh Posts: 5,837
    edited 2023-06-15 04:00

    Unfortunatly after this update, something broke and now my USB keyboard, mouse and gamepads are not detected anymore. :( I also updated to the latest flexspin (v 6.2) in case running an older variant was the reason for this problem. But it still didn't fix it. I was previously working with the older usbnew version in commit bce6e7f70d4c8a3f1c26a4f5f003439454152ec1 and that was working with my devices, so something since broke it...trying to figure it out.

    Update: Getting closer to pinpointing - build from Jun 9 (83318b3) still works, but top of master does not...

    Update2: found it! Looks like you are overriding the USB base pin now from the parent as of two days ago (checkin 3c80dd3) . I wasn't using this default pin and always overriding in the child, but the parent object now has priority. Glad I finally figured it out and it works again. :smile:

  • I just realized I missed the Live Forum 😞

  • evanhevanh Posts: 16,023

    The last info about live forum on the forums is almost a year old ... I think - The year number isn't actually specified.

  • In terms of controller compatibility, I just tried a Logitech F710 and it works, but strangely not on the root port, only on a hub. P2 board is currently doing standalone neoyume duty, so can't get more diagnostics currently. Switch on the back should be set to "X" for automatically correct layout.

    Perhaps useful to know if you want to use a P2 to control your DIY submarine.

  • pik33pik33 Posts: 2,383

    I reported the DB9 joystick interface as supported. However, there are limits:

    • if connected to the root port, OK
    • if connected to the USB HUB it has to be connected before the P2 (or maybe rather driver) starts. Then it works. If connected, or reconnected after, it does not work.

    I am now trying to add a joystick support to the retro interpreter, so it seems I will test more toys. I have also (somewhere in the drawer) a C64 old style USB joystick. My cheap pad didn't work with the usbnew, but this was several versions ago, so maybe it is worth to try if something changed.

  • @pik33 said:

    • if connected to the root port, OK
    • if connected to the USB HUB it has to be connected before the P2 (or maybe rather driver) starts. Then it works. If connected, or reconnected after, it does not work.

    Does it work if you re-connect the hub with the thing already plugged in?

  • pik33pik33 Posts: 2,383

    Yes, reconnecting the hub makes it work again.

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:04

    The joystick interface cannot be read via hidpad_axis(dev,axnum). up, or down, left, or right, it is always $FFFF8000
    However, there are useful data somewhere. At position 226,227,228 beginning from @hidpad_report I have horizontal axis (81,7f or 0), vertical axis (the same) and button. The "position"/ ID of the device is now 2 , but the data are on the same place if the device=3 or 1 too (the keyboard is hardwired to #0)

    ... edit: and these positions are simply raw report buffer as I can also see a keyboard and a mouse there
    ... edit 2: disabled 'hpad_normalize" procedure in usbnew. Now hidpad_axis returns useful values..
    ... edit 3: hpad_normalize gets good input data. lminmax is 0081007F, size=8.

    Now, why signx htmp1, #15 wc ? That will fail on 8 bit data.

  • @pik33 can you dump the HID descriptor? Sounds like it's not correctly detecting the range of the axis.

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:07

    Now, the problem was the normalize procedure. That version works for me:

    That version works for me:

    hpad_normalize  mov     htmp, hidr_lminmax  wz
                    if_z    mov     htmp, hidr_pminmax  wz
            if_z    ret
                    getword htmp1, htmp, #1      ' htmp1 = min
                    getword htmp,  htmp, #0      ' htmp = max
                    sub     hidr_size,#1
                    signx   htmp1, hidr_size    wc
            if_c    signx   retval, hidr_size
            if_c    add     hidr_size, #1
                    subs    htmp, htmp1         ' htmp = (max - min)
                    subs    retval, htmp1       ' retval = (retval - min)
                    shl     retval, #16         ' retval = (retval - min) << 16
                    subs    retval, #1          ' retval = ((retval - min) << 16) - 1
                    abs     htmp            wc
                    testb   retval, #31     wz
                    abs     retval
                    qdiv    retval, htmp
                    getqx   retval
        if_c_ne_z   neg     retval              ' retval = (((retval - min) << 16) - 1) / (max - min)
                    adds    retval, ##$8000 signx 15
                    ret
    

    hpad_normalize gets good input data. lminmax is 0081007F, size=8.

    Why there is signx htmp1, #15 wc ? That will fail on 8 bit data. Replaced by hidr_size-1

  • Idk @macca wrote that. I think the problem here is rather that the descriptor sets a min larger than the max. I think what should happen is that the axis gets reversed? Is 81 up/left or down/right?

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:15

    $81 is min - this is 8bit value, so it is -127, max is $7F, +127. We have data size=8, properly reported, so we should sign extend it from 8th bit, and then all works normal, left is now -32768, right is 32767 and a side effect of this asymetry is -1 at a neutral position.

  • No, that's not how it works I think, the values are supposed to be unsigned. In this case range is between 127 to 129. (normal analog stick would be between 0 and 255. Non-stupid digital controls also do that)

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:23

    The interface returns $81 left , 0 neutral and $7F right, so it is obvious that these are signed. There was hardcoded signx #15 in the driver, so whoever wrote that, thought about sign extending 16bit signed values. That of course failed with 8 bits.

    I don't have any other working game controller now to test the changed procedure

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:36

    There is more in it. This signx #15, wc tests also if we have signed or unsigned (16-bit) values. If min has its high bit set, that is signed, else it is unsigned. All is OK, only this hardcoded 15 has to be replaced by size-1

    I had to add a res for this... it seems it still works...

  • I don't think I have any where minimum value is not zero, so uhhhh I guess your idea is right? Might have to check HID spec. You said this thing worked before? How so? Does it also report as a hat?

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:42

    It worked in your test program before: it was recognized and changes values when moving. I didn't look very carefully at these values then. They were there, they changed on move. Today I tried to add "stick" command to the Basic and then I encountered the error. Left, or right, always $8000

    The joystick connected to it has one button that is recognized and can be read. I have now to call getcaps and see what it returns

  • okay, i think what might be happening is this: the logical maximum needs to be sign extended from the length which it has in the HID descriptor. The item can be coded as 0,1,2 or 4 bytes. I have one of the 0 to 255 pads connected and it codes its logical maximum as a two-byte value:

    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
    0x09, 0x04,        // Usage (Joystick)
    0xA1, 0x01,        // Collection (Application)
    0xA1, 0x02,        //   Collection (Logical)
    0x75, 0x08,        //     Report Size (8)
    0x95, 0x05,        //     Report Count (5)
    0x15, 0x00,        //     Logical Minimum (0)
    0x26, 0xFF, 0x00,  //     Logical Maximum (255)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0xFF, 0x00,  //     Physical Maximum (255)
    0x09, 0x30,        //     Usage (X)
    0x09, 0x31,        //     Usage (Y)
    0x09, 0x32,        //     Usage (Z)
    0x09, 0x32,        //     Usage (Z)
    0x09, 0x35,        //     Usage (Rz)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x04,        //     Report Size (4)
    0x95, 0x01,        //     Report Count (1)
    0x25, 0x07,        //     Logical Maximum (7)
    0x46, 0x3B, 0x01,  //     Physical Maximum (315)
    0x65, 0x14,        //     Unit (System: English Rotation, Length: Centimeter)
    0x09, 0x39,        //     Usage (Hat switch)
    0x81, 0x42,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
    0x65, 0x00,        //     Unit (None)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x0C,        //     Report Count (12)
    0x25, 0x01,        //     Logical Maximum (1)
    0x45, 0x01,        //     Physical Maximum (1)
    0x05, 0x09,        //     Usage Page (Button)
    0x19, 0x01,        //     Usage Minimum (0x01)
    0x29, 0x0C,        //     Usage Maximum (0x0C)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x06, 0x00, 0xFF,  //     Usage Page (Vendor Defined 0xFF00)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x08,        //     Report Count (8)
    0x25, 0x01,        //     Logical Maximum (1)
    0x45, 0x01,        //     Physical Maximum (1)
    0x09, 0x01,        //     Usage (0x01)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0xA1, 0x02,        //   Collection (Logical)
    0x75, 0x08,        //     Report Size (8)
    0x95, 0x07,        //     Report Count (7)
    0x46, 0xFF, 0x00,  //     Physical Maximum (255)
    0x26, 0xFF, 0x00,  //     Logical Maximum (255)
    0x09, 0x02,        //     Usage (0x02)
    0x91, 0x02,        //     Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0xC0,              //   End Collection
    0xC0,              // End Collection
    
    // 101 bytes
    
    
  • pik33pik33 Posts: 2,383

    It reports $30202, 2 buttons, 2 axes, 0 hats, all OK, the DB9 joy can have 2 independent buttons and there is no way to determine that there is only one in the connected device.

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 19:52
    hpad_normalize
                    mov     htmp, hidr_lminmax  wz
            if_z    mov     htmp, hidr_pminmax  wz
            if_z    ret
                    getword htmp1, htmp, #1     ' htmp1 = min
                    getword htmp, htmp, #0      ' htmp = max
                    mov     hidr_size2,hidr_size
                    sub     hidr_size2,#1
                    signx   htmp1, hidr_size2      wc
            if_c    sub     hidr_size, #1
            if_c    signx   retval, hidr_size
            if_c    add     hidr_size, #1
                    subs    htmp, htmp1         ' htmp = (max - min)
                    subs    retval, htmp1       ' retval = (retval - min)
                    shl     retval, #16         ' retval = (retval - min) << 16
                    subs    retval, #1          ' retval = ((retval - min) << 16) - 1
                    abs     htmp            wc
                    testb   retval, #31     wz
                    abs     retval
                    qdiv    retval, htmp
                    getqx   retval
        if_c_ne_z   neg     retval              ' retval = (((retval - min) << 16) - 1) / (max - min)
                    adds    retval, ##$8000 signx 15
                    ret
    

    This hdr_size2 (added a res where they are) is ugly but I don't have any better ideas now to replace #15 by size-1 without destroying the rest of the procedure.

  • Try reverting the normalize routine and instead putting this further up at .next

    .next
                    cmps    pa, #0      wcz
            if_be   ret     wcz
    
                    rdbyte  hpar1, ptra++
                    sub     pa, #1
                    mov     hpar2, #0
    
                    mov     htmp, hpar1
                    and     htmp, #$03
                    cmp     htmp, #1    wz
            if_z    rdbyte  hpar2, ptra++
            if_z    signx   hpar2,#7
            if_z    sub     pa, #1
                    cmp     htmp, #2    wz
            if_z    rdword  hpar2, ptra++
            if_z    signx   hpar2,#15
            if_z    sub     pa, #2
                    cmp     htmp, #3    wz
            if_z    rdlong  hpar2, ptra++
            if_z    sub     pa, #4
    
  • (Also, unrelatedly, instead of the mov/sub nonsense above, remember that ALTS also works on immediate values, so ALTS something,#511 will substitute something - 1 into next instruction's immediate)

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 20:20

    That alts is the simplest thing that works.

    alts    hidr_size,#511
    signx   htmp1, #0-0 wc     
    
  • But that's not really the correct fix, eitherhow.

  • I've put the fix on github btw.

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 20:30

    Why?

    For unsigned values min should be zero, and at least should have its high bit not set. Then signx will not do anything at all, carry will not be set, and retval will be not sign extended.
    For signed values, the minimum is less than zero, so it has its high bit set. Then signx will set the carry flag and retval will be sign extended

    Retval was already sign extended from size-1, only min was not, hardcoded at #15 instead.

    As we are now sign extending from size-1, that will work for all data sizes.

    I don't see any errors in it now.

  • The size-1 thing is just wrong. The meaning of logical minimum doesn't change based on report size. It needs to be extended at the point where it's read from the report, that appears to be the correct behaviour. Though in practice I'm not sure you'll ever find a device with a descriptor that fails with your fix.

  • pik33pik33 Posts: 2,383
    edited 2023-08-14 20:41

    The minimum should be reported at the same (or at least not less) size as the value. If reported as wider size, nothing bad can happen. If the min is $81, it can be reported as $FF81 or $FFFFFF81. Or maybe even $F81 or $FFF81 :) In all cases, when extended from #7, it will be converted to $FFFFFF81 and a carry flag will be set, to extend also the value, which is necessary when it's signed.

Sign In or Register to comment.