Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support 2MB card, change support 4/8MB card #23

Open
ELD400 opened this issue Dec 28, 2024 · 20 comments
Open

add support 2MB card, change support 4/8MB card #23

ELD400 opened this issue Dec 28, 2024 · 20 comments

Comments

@ELD400
Copy link

ELD400 commented Dec 28, 2024

on main.py
add support 2MB card
change detection of 4MB or 8MB card
(have 2 chips 2MB second have 4 chips 2Mb, wireshark see jdm make 6 call at some adress and check the reply, if cal 5 and 6 is not the same, they have not chip 3 and 4)

on jdmtool list, change alternately the color of the text, it's easier to follow the lines

on _transfer_skybound, add option (fullerase) to have possiblility to erase all the card before write database
on _transfer_skybound, add check if we have 'media/card_size_min' and 'media/card_size_max' on services.xml
on _transfer_skybound, add test for new_metadata on 2MB card

on cmd_transfer add fullerase args for transfer

on cmd_detect move select_page(0) on get_iid and get_unknown, because select_page it' must be sefine before call get_iid or get_unknown
on cmd_detect move get_unknown before , get_iid (like in wireshark)
on cmd_detect call set_led

on cmd_write_metadata test if card is 2MB or 4MB

on _write_database add parameter to get fullerase value
on _write_database add fullerase

on main add_argument fullerase for transfert

on main add_argument fullcard for read-database to have full image of card

on skybound.py

add support 2MB card
add one call write(b"\x50\x03") on get_unknown, because after insert card, the first call write(b"\x50\x03"), return value can be wrong, other call after is ok

rewrite get_iid function to detect carrectly 4 or 8MB card , via get_unknown it's not possible, on same type card (8MB for me) get_unknown return different value.

files.zip

on jum.log:
G2 firmware v:20140530 isG2Orange: 1 Card:032: 2 MB Intel Series 2 (1 MB x 2) IID:0x8900A200 isOrangeCard: 0
G2 firmware v:20140530 isG2Orange: 1 Card:421: 4 MB AMD Series C/D (2 MB x 2) IID:0x0100AD00 isOrangeCard: 0
G2 firmware v:20140530 isG2Orange: 1 Card:441: 8 MB AMD Series C/D (2 MB x 4) IID:0x0100AD00 isOrangeCard: 0
G2 firmware v:20140530 isG2Orange: 1 Card:451: 16MB AMD Series C/D (4 MB x 4) IID:0x89007E00 isOrangeCard: 1
G2 firmware v:20140530 isG2Orange: 1 Card:451: 16MB AMD Series C/D (4 MB x 4) IID:0x01004100 isOrangeCard: 1

@ELD400 ELD400 changed the title add support 2MB card, change support 4/8MB card add support one 16MB card add support 2MB card, change support 4/8MB card Dec 28, 2024
@dimaryaz
Copy link
Owner

Oh, interesting!

Could you send me your Wireshark captures for 2MB, 4MB, and 8MB? (Just the "detect" part - don't need any transfers.)

I'm trying to understand and simplify your get_iid() and get_unknown() code. I knew they work correctly only after when we select the right page - and of course, we don't know how to select a page until we know the memory layout, so this is circular logic. But, the memory offset 0 is the same for all cards, so I assumed that was the answer.

But, looks like your code calls it for different offsets. Don't know if you noticed, but your write statements match the offsets:

    MEMORY_OFFSETS = [0x00E0, 0x02E0, 0x0160, 0x0360, 0x01A0, 0x03A0, 0x01C0, 0x03C0]

    ...

            if 0 <= i <= 2:
                self.write(b"\x30\x00\x00\xe0\x00" ) # MEMORY_OFFSETS[0]
            elif i == 3:
                self.write(b"\x30\x00\x00\x60\x01" ) # MEMORY_OFFSETS[2]
            elif i == 4:
                self.write(b"\x30\x00\x00\xa0\x01" ) # MEMORY_OFFSETS[4]
            elif i == 5:
                self.write(b"\x30\x00\x00\xc0\x01" ) # MEMORY_OFFSETS[6]

So I'm hoping this can become something like:

select_page(0)
get_iid()
if at_least_4mb:
  select_page(...)
  get_iid()
  if at_least_8mb:
    select_page(...)
    get_iid()

@dimaryaz
Copy link
Owner

Actually, it could be even dumber than that: maybe the logic is, "Try reading offsets 4 and 6; if they work, it's 8MB; if they don't work, it's 4MB".

And it looks like you are right - get_unknown() has to be called before get_iid(), or need to select the page again. Even calling get_unknown() twice in a row returns different values.

Can you try this version of cmd_detect, and see if its output is helpful for telling the difference between 4MB and 8MB?

@with_usb
def cmd_detect(dev: SkyboundDevice) -> None:
    version = dev.get_version()
    print(f"Firmware version: {version}")
    if dev.has_card():
        print("Card inserted:")
        dev.select_page(0)
        dev.before_read()
        iid = dev.get_iid()
        print(f"  IID: 0x{iid:08x}")

        for offset in [0, 2, 4, 6]:
            dev.select_physical_page(dev.MEMORY_OFFSETS[offset])
            dev.before_read()
            dev.write(b"\x50\x03")
            buf = dev.read(0x0040)
            unknown = int.from_bytes(buf, 'little')
            print(f"  Unknown from offset {offset}: 0x{unknown:08x}")
    else:
        print("No card")

@ELD400
Copy link
Author

ELD400 commented Dec 28, 2024

I have no backup Wireshark captures (if it's needed I can make new one)
on capture we can see 3 first call with offset 0 (but if it's 2MB, he continue with write(b"\x50\x03"), in all other case with write(b"\x50\x04") ... (2MB is intel chip, other are AMD, maybe for this reason ...)

Don't know if you noticed, but your write statements match the offsets:

Sorry no ;-), your code is more beautifull , my code contain some subtilities, don't forget this (like write(b"\x50\x04") or write(b"\x50\x03")

on call 5 and 6 value return is not all the this the same value, for this reason I store value on call 4 ( last buff1)
( for example if I change the G2 device (black version/orange version, value change again)

Unknown identifier work correctly for 2MB for other case , it's not constant, for the same card size value change from one card to one other.

I make all test with :

  • 2 G2, one black, one orange in some case not all the time same value if we not respect some oder in command
  • 2x16MB card, 2x8MB, 2x 4 Mb, 1x 2MB

@ELD400
Copy link
Author

ELD400 commented Dec 28, 2024

Actually, it could be even dumber than that: maybe the logic is, "Try reading offsets 4 and 6; if they work, it's 8MB; if they don't work, it's 4MB".

And it looks like you are right - get_unknown() has to be called before get_iid(), or need to select the page again. Even calling get_unknown() twice in a row returns different values.

Can you try this version of cmd_detect, and see if its output is helpful for telling the difference between 4MB and 8MB?

@with_usb
def cmd_detect(dev: SkyboundDevice) -> None:
    version = dev.get_version()
    print(f"Firmware version: {version}")
    if dev.has_card():
        print("Card inserted:")
        dev.select_page(0)
        dev.before_read()
        iid = dev.get_iid()
        print(f"  IID: 0x{iid:08x}")

        for offset in [0, 2, 4, 6]:
            dev.select_physical_page(dev.MEMORY_OFFSETS[offset])
            dev.before_read()
            dev.write(b"\x50\x03")
            buf = dev.read(0x0040)
            unknown = int.from_bytes(buf, 'little')
            print(f"  Unknown from offset {offset}: 0x{unknown:08x}")
    else:
        print("No card")

PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 026: ID 0e39:1250
Detected data card:421, 4MB non-WAAS
Found device: Bus 001 Device 026: ID 0e39:1250
Could not open device: LIBUSB_ERROR_ACCESS [-3]

@dimaryaz
Copy link
Owner

Oh damn, I figured out what "get_unknown" actually does. It literally just reads 2 bytes from the data card (and interleaves them with 0s for some reason, so it returns 4 bytes). Normally, JDM reads one block (4 KB) at a time - and I'm guessing \x50\x03 is just a quick way to test if reading works or fails, without having to read the whole block.

I wrote "Hello, World!" to the card:

$ cat hello.txt 
Hello, World!
$ jdmtool write-database hello.txt
...

Then called \x50\x03 a bunch of times:

        dev.select_page(0)
        dev.before_read()
        for i in range(0x10):
            dev.write(b"\x50\x03")
            buf = dev.read(0x004)
            print(buf)

And it just returns the bytes of "Hello, World!":

$ jdmtool detect
Found device: Bus 001 Device 010: ID 0e39:1250
Firmware version: 20071203
Card inserted:
  IID: 0x01004100
bytearray(b'\x00e\x00H')
bytearray(b'\x00l\x00e')
bytearray(b'\x00l\x00l')
bytearray(b'\x00o\x00l')
bytearray(b'\x00,\x00o')
bytearray(b'\x00 \x00,')
bytearray(b'\x00W\x00 ')
bytearray(b'\x00o\x00W')
bytearray(b'\x00r\x00o')
bytearray(b'\x00l\x00r')
bytearray(b'\x00d\x00l')
bytearray(b'\x00!\x00d')
bytearray(b'\x00\n\x00!')
bytearray(b'\x00\xff\x00\n')
bytearray(b'\x00\xff\x00\xff')
bytearray(b'\x00\xff\x00\xff')

So that of course explains why it returns the same number for the same card, but different numbers for different cards...

@dimaryaz
Copy link
Owner

As for your LIBUSB_ERROR_ACCESS - don't know what happened there. Try unplugging it and plugging it again? Though if the code you tried makes it happen every time, then that's a problem.

@dimaryaz
Copy link
Owner

It's possible that, for example, a 4MB card treats offsets 0 and 4 as the same, and 2 and 6 as the same. So if they return different values, then you know it's 8MB.

But, if they are the same, it could still be 8MB, since it really depends on the contents of the card. E.g., if you completely erase the card, then calling \x50\x03 will return \x00\xff\x00\xff everywhere, so there will be no way to know what card it is.

Anyways, I can just add command-line arguments --4mb and --8mb to set the card type. It'll work until we find a real solution.

@ELD400
Copy link
Author

ELD400 commented Dec 29, 2024

Actually, it could be even dumber than that: maybe the logic is, "Try reading offsets 4 and 6; if they work, it's 8MB; if they don't work, it's 4MB".
when you say "not work", what do you means (in all case G2 return value) ?

My code try to reproduce exactly, request made by jdm, include for 2MB.

I think 'write(b"\x50\x04")' return device id from register on chip

I have optimized code like as you suggested :
for offset in [0,0,4,6]
self.select_physical_page(self.MEMORY_OFFSETS[offset])
files with corrections and with add command to clear all bytes on card
files.zip

on 2M we have 2 chips
on 4M we have 2 chips
on 8M we have 4 chips
on 16M 4 we have 4 chips

from jdm log :
Card:032: 2 MB Intel Series 2 (1 MB x 2)
Card:421: 4 MB AMD Series C/D (2 MB x 2)
Card:441: 8 MB AMD Series C/D (2 MB x 4)
Card:451: 16MB AMD Series C/D (4 MB x 4)
Card:451: 16MB AMD Series C/D (4 MB x 4)

get_iid with trace and without

2MB (For 2 MB it's different, he use b'\05\x04 and after b'\05\x03)
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 022: ID 0e39:1250
offset:0, nb_chip:1, iid:8900a200, query_string: b'P\x03' MEMORY_OFFSETS: 0x00e0
offset:0, nb_chip:2, iid:8900a200, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:2, iid:90009000, query_string: b'P\x03' MEMORY_OFFSETS: 0x01a0
offset:6, nb_chip:2, iid:90009000, query_string: b'P\x03' MEMORY_OFFSETS: 0x01c0
Detected data card:032 2MB, 2 chips Intel
Firmware version: 20071203
Card inserted:
IID: 0x8900a200
Unknown identifier: 0x8900a200

4MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 021: ID 0e39:1250
offset:0, nb_chip:1, iid:2000e700, query_string: b'P\x03' MEMORY_OFFSETS: 0x00e0
offset:0, nb_chip:2, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:2, iid:90009000, query_string: b'P\x04' MEMORY_OFFSETS: 0x01a0
offset:6, nb_chip:2, iid:90009000, query_string: b'P\x04' MEMORY_OFFSETS: 0x01c0
Detected data card:421, 4MB, 2 chips AMD, non-WAAS
Firmware version: 20071203
Card inserted:
IID: 0x0100ad00
Unknown identifier: 0x2000e700

8MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 020: ID 0e39:1250
offset:0, nb_chip:1, iid:2000e700, query_string: b'P\x03' MEMORY_OFFSETS: 0x00e0
offset:0, nb_chip:2, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:3, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x01a0
offset:6, nb_chip:4, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x01c0
Detected data card:441, 8MB, 4 chips AMD, non-WAAS
Firmware version: 20071203
Card inserted:
IID: 0x0100ad00
Unknown identifier: 0x2000e700

16MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 023: ID 0e39:1250
offset:0, nb_chip:1, iid:eb003c00, query_string: b'P\x03' MEMORY_OFFSETS: 0x00e0
offset:0, nb_chip:2, iid:89007e00, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:3, iid:89007e00, query_string: b'P\x04' MEMORY_OFFSETS: 0x01a0
offset:6, nb_chip:4, iid:89007e00, query_string: b'P\x04' MEMORY_OFFSETS: 0x01c0
Detected data card:451 16MB, 4 chips AMD, WAAS (orange)
Firmware version: 20140530
Card inserted:
IID: 0x89007e00
Unknown identifier: 0xeb003c00

16MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 023: ID 0e39:1250
Detected data card:451 16MB, 4 chips AMD, WAAS (orange)
Firmware version: 20140530
Card inserted:
IID: 0x89007e00
Unknown identifier: 0xeb003c00

8MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 024: ID 0e39:1250
Detected data card:441, 8MB, 4 chips AMD, non-WAAS
Firmware version: 20071203
Card inserted:
IID: 0x0100ad00
Unknown identifier: 0x2000e700

4MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 025: ID 0e39:1250
Detected data card:421, 4MB, 2 chips AMD, non-WAAS
Firmware version: 20071203
Card inserted:
IID: 0x0100ad00
Unknown identifier: 0x2000e700

2MB
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 026: ID 0e39:1250
Detected data card:032 2MB, 2 chips Intel
Firmware version: 20071203
Card inserted:
IID: 0x8900a200
Unknown identifier: 0x8900a200

@dimaryaz
Copy link
Owner

I think the files.zip you attached doesn't actually have your changes...

But in any case, your log still gives me enough information that I think I have a good solution! Try the fix_4mb_8mb branch. (Or see #24)

I'm pretty sure that "unknown" is useless here - it just reads bytes from the data card, so its value is only based on the contents of the card, not the type of the card. But, your output shows that IID can be different depending on the offset:

4MB
offset:0, nb_chip:2, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:2, iid:90009000, query_string: b'P\x04' MEMORY_OFFSETS: 0x01a0

8MB
offset:0, nb_chip:2, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x00e0
offset:4, nb_chip:3, iid:0100ad00, query_string: b'P\x04' MEMORY_OFFSETS: 0x01a0

So that's good enough! I'm now checking if the IID at offset 0x01a0 is 0x0100ad00 or 0x90009000. (I guess this is not exactly what JDM does, but I really cannot think of a reason to use \x50\x03...)

Anyways, see if works correctly for you now. Also, jdmtool detect will print IID at four offsets, just for debugging.

@dimaryaz
Copy link
Owner

dimaryaz commented Dec 30, 2024

I went back to reverse-engineering JDM, in case I find anything else useful. Turns out, all of the card programmer logic is in plugins/G2_libusb/G2_plugin.exe. You can run it by itself (without JDM), and then access it using curl (works in Windows 10 - I guess it comes with curl now?):

curl --data "{\"jsonrpc\": \"2.0\", \"method\": \"getstatus\", \"params\": {}, \"id\": \"1\"}" http://localhost:8006

Response:

{
  "id":"0",
  "jsonrpc":"2.0",
  "result":[{
    "bus_addr":"1_2",
    "carddesc":"16 MB WAAS,silver label",
    "cardsizebytes":"16777216",
    "cardstyle":"Garmin",
    "jeppdrivedll":"20071203",
    "lastupdateGMT":"Mon Dec 30 14:40:46 2024",
    "memorytype":4,
    "sig":1037578355,
    "sigidx":"0",
    "techsupportdesc":"[0]g2_plugin v:3.2.1.0 G2 firmware v:20071203 isG2Orange: 0 Card:451: 16 MB AMD Series C/D (4 MB x 4)  JDA version:1.0.0.6 IID:0x1004100 isOrangeCard: 0"
  }]
}

(I'm now trying to find a way to modify IID in the debugger, to simulate other cards...)

@dimaryaz
Copy link
Owner

I figured out how to intercept the memory offset and the IID in a debugger, so I was able to test every combination!

Turns out, there is also a 6MB card! So JDM tests the four chips at the four memory offsets: 0x00E0, 0x0160, 0x01A0, 0x01C0.

Results:

0x00E0 0x0160 0x01A0 0x01C0 Result
? ? ? No card
X ? ? No card (even though the first chip is present)
X X 4MB
X X X 6MB
X X X X 8MB
X X X 8MB (even though the third chip is missing!)

I will update the code now.

And, this is what it took to figure it out :)

VirtualBox_Windows 10_30_12_2024_16_06_12

@ELD400
Copy link
Author

ELD400 commented Dec 31, 2024

Whell,
when I tell you that there were subtleties in my code, it was to easily take into account the memories not yet supported, and therefore the ones at the 4 addresses, and so why I tested at the 4 addresses.
there are also 2Mb, 3MB, 6MB cards.
My tests are progressing, there are still differences that when I am testing between a G2 black and a G2 orange, the result is different when there is no memory at the tested location

I make test with PAGES_PER_OFFSET with value 10, 20 or #40, depending of size of chip memory ( 1MB, 2MB, 4MB)
From datasheet of memory, all have same BLOCK_SIZE, only BLOCKS_PER_PAGE change.
(I think this why you have a strange MEMORY_LAYOUT for 16MB card), it's not 8 memory chips, but it's 4 memory, with BLOCKS_PER_PAGE= 0x40), same for 2MB card (on datasheet of memory I find BLOCKS_PER_PAGE= 0x10 for 1MB chip and x40 for 4MB chip)

2MB Card (2x 1MB chips->blocksize =64k(=0x1000)->16(x10) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x10/memory
3MB Card (3x 1MB chips->blocksize =64k(=0x1000)->16(x10) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x10/memory
4MB Card (2x 2MB chips->blocksize =64k(=0x1000)->32(x20) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x20/memory
6MB Card (3x 2MB chips->blocksize =64k(=0x1000)->32(x20) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x20/memory
8MB Card (4x 2MB chips->blocksize =64k(=0x1000)->32(x20) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x20/memory
16MBCard (4x 4MB chips->blocksize =64k(=0x1000)->64(x40) PAGES_PER_OFFSET of 65K->PAGES_PER_OFFSET=0x40/memory

in this case the MEMORY_LAYOUT would map the number of memory chip and look like this
MEMORY_LAYOUT_2MB = [0, 1] # 2x1MB chips memory
MEMORY_LAYOUT_4MB = [0, 1] # 2x2MB chips memory
MEMORY_LAYOUT_8MB = [0, 1, 2, 3] # 4x2MB chips memory
MEMORY_LAYOUT_16MB =[0, 1, 2, 3] # 4x4MB chips memory
For 1MB
For 2MB
For 4MB

and maybe :
MEMORY_LAYOUT_3MB = [0, 1, 2] # 3x1MB chips memory, PAGES_PER_OFFSET=0x10
MEMORY_LAYOUT_6MB = [0, 1, 2] # 3x2MB chips memory, PAGES_PER_OFFSET=0x20
but this can impact translate_page function.

in my test code I update PAGES_PER_OFFSET during with_data_card function to update PAGES_PER_OFFSET with the good value
depending of size of memory chip and MEMORY_LAYOUT depending of number of memory chip .

I will check how jdm work during programing for 2MB card, because for now, write_database is not supported, program crash (timeout on first write), for read-database, he pass, but I must will check it's a good mapping for pages.

sorry for delayed answers, I am in GMT+1 time zone.

@dimaryaz
Copy link
Owner

Got it.

I just implemented the new logic and pushed it to main before I saw your response. I'm pretty confident that it will at least work for 4/6/8MB (I even added unit tests!) - but try it and see.

And yeah, let me know if you figure out the correct PAGES_PER_OFFSET and BLOCKS_PER_PAGE. I guessed all of that by capturing JDM's USB data, without any understanding of how the chips actually work.

@ELD400
Copy link
Author

ELD400 commented Dec 31, 2024

this is not a criticism, it is already a huge and well written work (i am not a python dev)

congratulations for the work done

@dimaryaz
Copy link
Owner

Oh, don't worry! I want to get it right. And thank you.

@ELD400
Copy link
Author

ELD400 commented Dec 31, 2024

Test your change with 4 cards and 2 G2 (black and orange)
Card: 2, 4, 8, 16MB

PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 062: ID 0e39:1250
Detected data card: 2MB
Firmware version: 20071203, G2 black
Card inserted:
IID at offset 0x00e0: 0x8900a200
IID at offset 0x0160: 0x8900a200
IID at offset 0x01a0: 0x90009000
IID at offset 0x01c0: 0x90009000
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 063: ID 0e39:1250
Detected data card: 2MB
Firmware version: 20140530, G2 Orange
Card inserted:
IID at offset 0x00e0: 0x8900a200
IID at offset 0x0160: 0x8900a200
IID at offset 0x01a0: 0xff00ff00
IID at offset 0x01c0: 0xff00ff00

PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 064: ID 0e39:1250
Detected data card: 4MB
Firmware version: 20071203, G2 black
Card inserted:
IID at offset 0x00e0: 0x0100ad00
IID at offset 0x0160: 0x0100ad00
IID at offset 0x01a0: 0x90009000
IID at offset 0x01c0: 0x90009000
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 004: ID 0e39:1250
Detected data card: 4MB
Firmware version: 20140530, G2 Orange
Card inserted:
IID at offset 0x00e0: 0x0100ad00
IID at offset 0x0160: 0x0100ad00
IID at offset 0x01a0: 0xff00ff00
IID at offset 0x01c0: 0xff00ff00

PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 002: ID 0e39:1250
Detected data card: 8MB
Firmware version: 20071203, G2 black
Card inserted:
IID at offset 0x00e0: 0x0100ad00
IID at offset 0x0160: 0x0100ad00
IID at offset 0x01a0: 0x0100ad00
IID at offset 0x01c0: 0x0100ad00
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 005: ID 0e39:1250
Detected data card: 8MB
Firmware version: 20140530, G2 Orange
Card inserted:
IID at offset 0x00e0: 0x0100ad00
IID at offset 0x0160: 0x0100ad00
IID at offset 0x01a0: 0x0100ad00
IID at offset 0x01c0: 0x0100ad00

PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 010: ID 0e39:1250
Detected data card: 16MB WAAS (orange)
Firmware version: 20140530, G2 Orange
Card inserted:
IID at offset 0x00e0: 0x89007e00
IID at offset 0x0160: 0x89007e00
IID at offset 0x01a0: 0x89007e00
IID at offset 0x01c0: 0x89007e00
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 012: ID 0e39:1250
Detected data card: 16MB WAAS (orange)
Firmware version: 20071203, G2 black
Card inserted:
IID at offset 0x00e0: 0x89007e00
IID at offset 0x0160: 0x89007e00
IID at offset 0x01a0: 0x89007e00
IID at offset 0x01c0: 0x89007e00

with bad card :
PS C:\Users\ABC> jdmtool detect
Found device: Bus 001 Device 015: ID 0e39:1250
Unexpected IID 0xeb00eb00, chip_idx: 0
Unexpected IID 0x6e006e00, chip_idx: 1
Unexpected IID 0x28002800, chip_idx: 2
Unexpected IID 0xdc00dc00, chip_idx: 3
Unknown data card. Please file a bug!

find files with amend

  • detect card correctly with G2 black and G2 Orange
  • add --fullerase on write database
  • add --fullcard with read-database (to have full copy of card, before write new file on card for example)
  • add jdmtool clear-card to blank card with (0xff)
  • add mark in green one line out of 2 on jdmtool list, so easy to find line when you have a lot of lines on list
  • in of Unexpected IID, add more detail to have info
  • add warning, before write, if card is too small or if card_size_min/card_size_max is not define on services.xml file
  • add text to know if it's G2 black or Orange when display firmware of G2

files.zip

maybe we can add mode verbose to display this info or other only if needed :
Card inserted:
IID at offset 0x00e0: 0x8900a200
IID at offset 0x0160: 0x8900a200
IID at offset 0x01a0: 0x90009000
IID at offset 0x01c0: 0x90009000

I must rewrite code to test my logic for PAGES_PER_OFFSET and BLOCKS_PER_PAGE, maybe not today (31/12/24)....

I don't want read page in bad order, like page1,page3,page2,pag4 ...
I think the logic PAGES_PER_OFFSET and BLOCKS_PER_PAGE is good, but I hope G2 don't conplicate this, because we not access directly to memory, but through the G2, we speek with G2, G2 speak with memory ....

I try to get a 3MB card today on airport.

@ELD400
Copy link
Author

ELD400 commented Jan 1, 2025

Update for 1MB, implement write and erase

  • update write_block for 1MB chip
  • update erase_page for 1MB chip

add comment for G2 black or G2 Orange
ex:

jdmtool detect (because some difference sometime)
Found device: Bus 001 Device 038: ID 0e39:1250
Detected data card: 2MB
Firmware version: 20071203 (G2 black)
Card inserted:
IID 0x8900a200 at offset 0x00e0
IID 0x8900a200 at offset 0x0160
IID 0x90009000 at offset 0x01a0
IID 0x90009000 at offset 0x01c0

TODO : stop write if 16MB Orange card with G2 black

Update init_data_card for 3Mb card

  • implement new memory layout
    MEMORY_LAYOUT_2MB = [0, 1] # 2x1MB chips memory
    MEMORY_LAYOUT_3MB = [0, 1, 2] # 3x1MB chips memory
    MEMORY_LAYOUT_4MB = [0, 1] # 2x2MB chips memory
    MEMORY_LAYOUT_6MB = [0, 1, 2] # 3x2MB chips memory
    MEMORY_LAYOUT_8MB = [0, 1, 2, 3] # 4x2MB chips memory
    MEMORY_LAYOUT_16MB=[0, 1, 2, 3] # 4x4MB chips memory
  • implement sectors_per_chip
  • update translate_page for new memory layout and sectors_per_chip

files3.zip

test with 2,4,8,16MB card (read, write, erase, detect, transfer) and compare file after read card, with bin source

I hope this is okay (it can always be improved)

@dimaryaz
Copy link
Owner

dimaryaz commented Jan 2, 2025

Wow, the actual write and erase logic is different for 1MB chips, not just memory offsets.

While debugging JDM, I accidentally discovered that IID 0x8900a200 with 4 chips is a valid card: "034: 4 MB Intel Series 2 (1 MB x 4)" - which is also 4MB. So that means, MEMORY_LAYOUT_4MB isn't meaningful anymore. In fact, there is no point in using those constants and arrays anymore - just need the number of chips and size of each chip.

Also, I can see these string in JDM, but don't know which IID maps to them, so can't really test them:
"420: 4 MB Intel Series 2 (2 MB x 2)"
"430: 6 MB Intel Series 2 (2 MB x 3)"
This makes me wonder if the logic self.sectors_per_chip == 0x10 is correct, or if perhaps it's Intel vs AMD? But I don't know how to find out.

Anyways, I will try to understand your changes now...

@ELD400
Copy link
Author

ELD400 commented Jan 2, 2025

for me, iid is device id on datasheet
if we find iid 0x8900a200, that mean we find a chip type, on datasheet sectors_per_chip is fixed for one chip type.
if we know iid , we know sectors_per_chip because it's in relation with type of chip
if you detect 0x8900a200, it's 1MB intel chip, you count chip, you find it's 4 x 1MB (like you have see on code jdm)

it's true, MEMORY_LAYOUT can become CARD_TYPE (in relation with number of chips not chip type)

in my code for 4MB chip, I add 0x200 in an intertwined manner as in your MEMORY_LAYOUT_16MB

to support 4 x 1MB today we can use MEMORY_LAYOUT_4MB_INTEL = [0, 1, 2 ,3] # 4 chips
and

      elif nb_chip == 4:
            self.memory_layout = SkyboundDevice.MEMORY_LAYOUT_4MB_INTEL
            self.card_name = "4MBIntel"

@dimaryaz
Copy link
Owner

dimaryaz commented Jan 2, 2025

I started implementing the logic of the data card hardware in the data_card_mock branch: https://github.com/dimaryaz/jdmtool/blob/data_card_mock/tests/test_skybound.py

This way, we can use a "virtual" data card, without using the real hardware. It's not finished yet (only simulates IID and write - no erase or read yet). But, assuming it's correct, it accomplishes several things:

  • Documents everything you've discovered so far
  • Lets me test the jdmtool logic without having access to the 2MB, 4MB, etc. cards
  • Makes it easy to catch any new bugs

If you want to try it, install pytest, and run pytest -k skybound. It will fail with the existing code in the branch - but will pass with your changes in files3.zip. I can then refactor the logic, get rid of memory_layout, etc., and still be reasonably sure that it works correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants