Difference between revisions of "83Plus:OS:84 Plus USB Information"
(added wrongtitle template and first paragraph blurb) |
Graphmastur (Talk | contribs) m |
||
(156 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | |||
− | |||
− | |||
:I moved this page from Talk:83Plus:BCALLs:5254 to here because it seems to fit better. Please note that this is still a work in progress, and don't take the information as gold. I figured having an option for a Talk page for this would outweigh the moving of it. For the time being, we'll leave the data formatted as-is, since it's still nicely done. --[[User:AndyJ|AndyJ]] 07:44, 27 May 2005 (PDT) | :I moved this page from Talk:83Plus:BCALLs:5254 to here because it seems to fit better. Please note that this is still a work in progress, and don't take the information as gold. I figured having an option for a Talk page for this would outweigh the moving of it. For the time being, we'll leave the data formatted as-is, since it's still nicely done. --[[User:AndyJ|AndyJ]] 07:44, 27 May 2005 (PDT) | ||
Line 9: | Line 5: | ||
OK, I've started this talk page to post information about the 84 Plus USB. This isn't the ideal place, since not all of this stuff has to do with entry point 5254, but it'll have to do. If anyone else would like to contribute any information or thoughts, please do so. Much of this data has been discovered by analyzing how the EasyData application interacts with the EasyTemp probe. --[[User:Dan Englender|Dan Englender]] 22:32, 23 May 2005 (PDT) | OK, I've started this talk page to post information about the 84 Plus USB. This isn't the ideal place, since not all of this stuff has to do with entry point 5254, but it'll have to do. If anyone else would like to contribute any information or thoughts, please do so. Much of this data has been discovered by analyzing how the EasyData application interacts with the EasyTemp probe. --[[User:Dan Englender|Dan Englender]] 22:32, 23 May 2005 (PDT) | ||
+ | Many thanks to Olivier Armand for providing information invaluable to figuring out some of the harder to decipher USB ports. --[[User:Dan Englender|Dan Englender]] 23:25, 9 Jul 2005 (PDT) | ||
== Easy Data == | == Easy Data == | ||
Line 29: | Line 26: | ||
The 5260 and 5257 entry points are called right after each other in the code, and don't seem to take any input. I guess they're some kind of USB shut down. 5260 doesn't do much of anything other than set 9C1E to 0000. 5257 plays with the ports some, and then clears the callback address. Since the call back address gets called, I'm assuming it must also call the callback address somewhere in there. | The 5260 and 5257 entry points are called right after each other in the code, and don't seem to take any input. I guess they're some kind of USB shut down. 5260 doesn't do much of anything other than set 9C1E to 0000. 5257 plays with the ports some, and then clears the callback address. Since the call back address gets called, I'm assuming it must also call the callback address somewhere in there. | ||
− | === 525A | + | === 525A BCALL === |
− | 525A | + | 525A takes a pointer to a structure in HL. 9C1C will be set to the structure pointer. Some checks on port 4C and 8F are done at teh beginning of this call. A data segment of value: 21 09 0002 0000 0800 will be sent through the control data port. This cooresponds to Host to Device's endpoint, vendor type, set configuration. |
− | === 5290 | + | === 525D BCALL === |
+ | 525D takes a pointer to a structure in HL. The 525D entry point first checks to see if bit 3 of port 4C and bits 0 and 2 of port 8F are set. If they are not, it returns failure. These bits are not set by, say, plugging in the hardware. They are set, however, after 5254 has been called. After checking these bits, 9C1E is set to the passed structure pointer. If this value is zero, the routine will return failure. A value of 1 will be stored to HL+2, then a value of 1 will be output to port 8E, a value of 20h to port 94h, and success will be returned. | ||
+ | |||
+ | === 5290 BCALL === | ||
A BCALL to 5290 alone is enough to turn on the LED on EasyTemp. (Though it turns on to a strange orange color which is never seen during EasyData execution). It must do some sort of USB initialization type stuff. If bit 3,(iy+41) is set, 5290 will fail. So this must either be a USB-already-initialized flag, or a Don't-Use-USB flag I guess. | A BCALL to 5290 alone is enough to turn on the LED on EasyTemp. (Though it turns on to a strange orange color which is never seen during EasyData execution). It must do some sort of USB initialization type stuff. If bit 3,(iy+41) is set, 5290 will fail. So this must either be a USB-already-initialized flag, or a Don't-Use-USB flag I guess. | ||
+ | |||
+ | This BCALL appears to do the following: | ||
+ | # Do stuff | ||
+ | # Request the device descriptor with a maximum size of 8 bytes. | ||
+ | # Issue a Set Address Request, with an address of 2 | ||
+ | # Request the device descriptor again, this time with a 18 byte maximum data size. | ||
+ | # Check device description for an appropriate TI or Vernier device and quit if not found. | ||
+ | # Do stuff | ||
+ | |||
+ | Why are there two device descriptor requests? Presumably so that the calculator can check the peripheral's max packet size (which is in the first 8 bytes), so that it will know how to segmentize further traffic. | ||
+ | |||
+ | === 5293 BCALL === | ||
+ | This BCALL is enough to to turn the LED off on EasyTemp. It's called by 5260. | ||
=== Other === | === Other === | ||
Line 40: | Line 53: | ||
− | I'm, err, not exactly clear at this point how the app actually gets the temperature data from the EasyTemp probe, as the entry point seem to only be called on init and quit. The callback routine seemed a likely candidate, but it's not that either. Maybe there's something going on in the interrupt that I'm not aware of. Or maybe there are some more entry points used that I missed. | + | I'm, err, not exactly clear at this point how the app actually gets the temperature data from the EasyTemp probe, as the entry point seem to only be called on init and quit. The callback routine seemed a likely candidate, but it's not that either. Maybe there's something going on in the interrupt that I'm not aware of. Or maybe there are some more entry points used that I missed. ------- I'm now pretty sure that EasyData gets data through the 9C1E structure's callback which I believe returns data retrieved from an interrupt transfer in the OS's interrupt. |
Line 68: | Line 81: | ||
=== USB Data Table === | === USB Data Table === | ||
− | If the TableEntryType is 3, then the data will be USB data and will be formatted as follows: The first byte will be the number of entries in the USB data table. Then, each entry, starts with a byte. Not sure what that is. Then comes a word. Not really sure what that is either. But weird things happen if the high byte is not 00. | + | If the TableEntryType is 3, then the data will be USB data and will be formatted as follows: The first byte will be the number of entries in the USB data table. Then, each entry, starts with a byte. Not sure what that is, but B_CALL 5269h returns it. Then comes a word. Not really sure what that is either. But weird things happen if the high byte is not 00. If the high byte is not 00, it will skip two bytes in the table for every bit set. If the low byte is 01, only the vendor ID will be checked, if it's 02, only the product ID will be checked (why?), if it's 03, the vendor ID and the product ID will be checked. If it's 04, the product revision is checked for being greater than the device's revision. If it's 08, the product revision is checked for being less than or equal to the device's revision. Depending on the low byte of this word, the words that follow will be (in order) the vendor ID, product ID, and the two device revisions to check against. If the low byte is 03, for example, then the next word will be the vendor ID, and the following word will be the product ID. If both of these match a connected USB device, then the app will launch. |
=== FindSpecialAppHeader BCALL === | === FindSpecialAppHeader BCALL === | ||
Line 80: | Line 93: | ||
=== 5269 BCALL === | === 5269 BCALL === | ||
− | The 5269 BCALL is used by the OS after determining that an app with the USB special app header exists. | + | The 5269 BCALL is used by the OS after determining that an app with the USB special app header exists. This entry point compares the values in the USB app header data table with the values at 9C16, 9C18, and 9C1A (vendor ID, product ID, and product revision, respectively). Input is HL -> data table, B = page. Returns Z if found, NZ if not found. Also returns first byte of vendor/product/revision ID entry in A. The full disassembly of this routine on OS 2.41 is [http://www.brandonw.net/calcstuff/5269.txt here]. |
== Hardware == | == Hardware == | ||
Ports 55h and 56h are initially polled in the interrupt routine to determine USB activity. If activity is detected, 4Dh, 82h, 84h, 86h, 8Fh, 91h, and others may be polled as well. | Ports 55h and 56h are initially polled in the interrupt routine to determine USB activity. If activity is detected, 4Dh, 82h, 84h, 86h, 8Fh, 91h, and others may be polled as well. | ||
+ | |||
+ | === Port 4C === | ||
+ | Some sort of status port. Values of 1A or 5A and 12 or 52 mean something. Default value is 22. Some of the host routines make sure bit 3 is set. | ||
+ | |||
+ | === Port 4D === | ||
+ | Some sort of status port. Bit 4 is set if a type A cable is plugged in. The high nibble appears to be A if nothing is plugged in, and 6 while connected to the computer. The port is checked bit-wise, but I haven't quite figured out how the rest of the bits function yet. I'm as yet unsure whether the values of this port are set based on external events alone, or also influenced by stuff going on in the interrupt. Will check with interrupts disabled later. There is a routine that is called when the bit 1 port 56 event occurs which first waits for bit 6,4D to be reset (which seems like the standard condition after a peripheral has been plugged in). It then does some outputs to ports 3A, 39, 4C, and 8F; after which it waits for bit 6,4D to be set (which seems like the standard condition after a peripheral has been initialized). This doesn't exactly clarify what bit 6 actually means though. | ||
+ | |||
+ | === Port 55 === | ||
+ | This port determines whether there's USB activity for the interrupt routine to take notice of. If any of the first five bits of the port are reset, that means something's happening in USB land. | ||
+ | *bit 0 - Not sure. Only seems to happen with peripheral. | ||
+ | *bit 1 - ???? (not checked by OS) | ||
+ | *bit 2 - Check port 56 for details on what event has happened | ||
+ | *bit 3 - ???? (not checked by OS) | ||
+ | *bit 4 - Data waiting? Or read for data? Or something like this. | ||
=== Port 56 === | === Port 56 === | ||
− | The default value for port 56h is 00. If the | + | The default value for port 56h is 00. If bit 2 of port 55 is reset in the interrupt routine, this port should be checked to see what event occured. Each set bit indicates a particular event: |
+ | * bit 0 - I've seen this bit set while playing around, but the OS doesn't use it. | ||
+ | * bit 1 - Something to do with peripheral initialization? | ||
+ | * bit 2 - ?? | ||
+ | * bit 3 - ?? | ||
+ | * bit 4 - Plug-in, A-cable | ||
+ | * bit 5 - Unplug, A-cable | ||
+ | * bit 6 - Plug-in, B-cable | ||
+ | * bit 7 - Unplug, B-cable | ||
+ | |||
+ | === Port 57 === | ||
+ | Sending 0 to this port seems to acknowledge USB interrupts. | ||
+ | |||
+ | === Port 5B === | ||
+ | I think if you load a value of 0 to this port, it will stop the USB controller from issuing interrupts to the calculator. Writing a value of 1 enables USB-related interrupts again. | ||
+ | |||
+ | === Port 80 === | ||
+ | This input/output port holds the address for the device. Valid both when acting as peripheral and when acting as host. (Though the OS always assigns address 2 when acting as host.) | ||
+ | |||
+ | === Port 82 === | ||
+ | Indicates outgoing data success. Seems to be valid both for data packets, and for IN/OUT tokens. Each bit indicates data sent successfully for that Ax port. It seems that the control port's bit registers for both incoming and outgoing data (instead of using port 84). | ||
+ | |||
+ | === Port 83 === | ||
+ | I'm guessing that this is a continuation of port 82, with each bit indicating outgoing data success for endpoint/pipes A8 through AF. | ||
+ | |||
+ | === Port 84 === | ||
+ | Indicates incoming data ready. Each bit indicates data ready to read on that Ax port. The control pipe acts as if it were an out pipe though, so don't expect to see bit 0 set. Check port 82 for control data. | ||
+ | |||
+ | === Port 85 === | ||
+ | I'm guessing that this is a continuation of port 84, with each bit indicating incoming data ready for endpoint/pipes A8 through AF. | ||
+ | |||
+ | === Port 86 === | ||
+ | Some sort of status port. Seems to generally hold a value of 0. Bits 5 or 7 being set seems to be an error condition. Other bits may or may not be error conditions, though it's beginning to look like they'll all errors or abort-conditions of some kind. | ||
+ | |||
+ | === Port 87 === | ||
+ | This port might be a bitmap of which pipes in the Ax range are enabled for output. Port 88 would presumably be a continuation for pipes 8 through F. | ||
+ | |||
+ | === Port 89 === | ||
+ | This port might be a bitmap of which pipes in the Ax range are enabled for input. Port 8A would presumably be a continuation for pipes 8 through F. | ||
+ | |||
+ | === Port 8C === | ||
+ | The low byte of the 15-bit frame counter. It is automatically incremented if a cable is plugged in. I haven't timed it, but in theory it should be incremented about once per millisecond. | ||
+ | |||
+ | === Port 8D === | ||
+ | The high byte of the 15-bit frame counter. See port 8C. | ||
+ | |||
+ | === Port 8E === | ||
+ | This input/output port designates current endpoint to read from/transfer to. Can be 0-15. | ||
+ | |||
+ | === Port 8F === | ||
+ | Values of 1 or 3 are outputted to this port. I have no clue what they mean. After USB init, on read, it seems to be some sort of status. Bit 2 being set appears to imply calculator-as-host, reset seems to imply calculator-as-peripheral. Bit 3 set appears to mean B device, and reset means A device. | ||
+ | |||
+ | === Port 90 === | ||
+ | This port sets up the maximum packet size of outgoing pipes. See port 93. | ||
+ | |||
+ | === Port 91 === | ||
+ | This is the outgoing pipe command port. Port 82h seems to indicate when the command is ready. These bit values are valid in host mode on the control pipe, at least: | ||
+ | * bit 1 - set indicates command in host to device direction, reset indicates from device to host | ||
+ | * bit 3 - set means output data as SETUP packet/token? | ||
+ | * bit 5 - set means output IN token? Reset means OUT token? (compliment of bit 1?) | ||
+ | * bit 6 - reset means there is data associated with this command | ||
+ | So commands for the control pipe would look like: | ||
+ | *Send Control Command (no data) | ||
+ | *# Output SETUP data to port A0 | ||
+ | *# Output 0A to port 91 (setup token/data from host to device) | ||
+ | *# Output 60 to port 91 (go to status stage) | ||
+ | *Send Control Command (with incoming data) | ||
+ | *# Output SETUP data to port A0 | ||
+ | *# Output 0A to port 91 (setup token/data from host to device) | ||
+ | *# Output 20 to port 91 (request IN data) | ||
+ | *# Read data from port A0 | ||
+ | *# Output 42 to port 91 (go to status stage) | ||
+ | *SendControl Command (with outgoing data) | ||
+ | *# Output SETUP data to port A0 | ||
+ | *# Output 0A to port 91 (setup token/data from host to device) | ||
+ | *# Output data to port A0 | ||
+ | *# Output 02 to port 91 (OUT data) | ||
+ | *# Output 60 to port 91 (go to status stage) | ||
+ | On read, bits 2 or 4 being set indicate an error state. Bit 2 is stall, bit 4 is NAK. | ||
+ | |||
+ | === Port 93 === | ||
+ | This port sets up the maximum packet size for incoming pipes. Multiply the value of the port by 8 to get the packet size. You should probably only set one bit. I have no clue what would happen if you set more than one. | ||
+ | |||
+ | === Port 94 === | ||
+ | This is the incoming pipe command port. Similar to port 91. | ||
+ | |||
+ | === Port 96 === | ||
+ | Holds the low byte of the size of the received and buffered input data for the currently selected endpoint/pipe. Read the data from the appropriate Ax port. | ||
+ | |||
+ | === Port 97 === | ||
+ | Presumably holds the high byte of the size of the received and buffered input data fro the currently selected endpoint/pipe. The 84P doesn't actually send any packets larger than 256 bytes, so it's not used. | ||
+ | |||
+ | === Port 98 === | ||
+ | If the description of port 9A is even remotely right, then this port has a good chance of being the same thing, but for outgoing pipes. | ||
+ | |||
+ | === Port 99 === | ||
+ | While I'm making things up, if ports 98, 9A, and 9B are all correct, then maybe this is the interrupt interval for setup of outgoing interrupt pipes and 9B is incoming interrupt pipes. *shrug* | ||
+ | |||
+ | === Port 9A === | ||
+ | OK, this is quite a strech, long shot, guess, etc; but here are some possibilities for this port: This might set up incoming pipes. The high nibble might define the type of pipe. 2 would be bulk, and 3 would be interrupt. That might make 1 isochronous, but I'm not going to go there. The low nibble might be which pipe to map the current endpoint to. This cooresponds to the port in the AX range. So 21 would map an incoming bulk pipe to port A1h. Or, that could all be completely nonsense. | ||
+ | |||
+ | === Port 9B === | ||
+ | This might setup the poll interval for an interrupt endpoint. Or it might not. Just a thought. | ||
=== Port A0 === | === Port A0 === | ||
− | I | + | This is the control pipe data I/O port. I'm not sure if it's statically fixed this way, or if it is configured like the other pipes. |
+ | |||
+ | === Ports A1-A? === | ||
+ | Ports A1 and A2 are used by the OS as data I/O pipes and are set up via port 98 or 9A. It seems likely that more ports in the Ax range can be used as pipes, and I'm guessing all the ports A0-AF can be used. | ||
+ | |||
+ | == RAM == | ||
+ | === 9C13/9C14 === | ||
+ | 9C13 is the page, and 9C14 is the address of a callback routine. It is set by the 5254 BCALL, and called at various times. I'm not really sure what the callback routine is for yet. | ||
+ | |||
+ | === 9C16 === | ||
+ | This is where the vendor ID is stored. It is populated by at least the 5290 BCALL, and perhaps others. | ||
+ | |||
+ | === 9C18 === | ||
+ | This is where the product ID is stored. It is populated by at least the 5290 BCALL, and perhaps others. | ||
+ | |||
+ | === 9C1A === | ||
+ | This is where the device release number is stored. It is populated by at least the 5290 BCALL, and perhaps others. | ||
+ | |||
+ | === 9C1C === | ||
+ | A pointer to another structure. Similar to 9C1E. Output control transfers? | ||
+ | |||
+ | === 9C1E === | ||
+ | A pointer to some sort of structure. First word of structure is a pointer to some sort of receive buffer. Reads from port A1 may be stored here. Perhaps for interrupt transfers? Offset 2 of structure is a byte value. Offset 3 of structure is a callback page and address | ||
+ | |||
+ | === 9C26 === | ||
+ | Byte value representing device state (calc as peripheral) | ||
+ | *0 = Device in default state | ||
+ | *1 = Device in addressed state | ||
+ | *2 = Device in configured state | ||
+ | |||
+ | === 9C27 === | ||
+ | Another byte denoting something about the current state or operation. A value of 1 might imply a host->periph communication and a value of 2 might imply a periph->host communication. | ||
+ | |||
+ | === 9C28 === | ||
+ | Current USB status, or something like that. | ||
+ | *1 = in the middle of USB host initialization | ||
+ | *2 = Background intialization complete? | ||
+ | *3 = Explicit (5290) initialization complete? | ||
+ | *4 =???? | ||
+ | *5 = Something to do with uninit? | ||
+ | *6 = Something to do with error states? | ||
+ | |||
+ | === 9C29 === | ||
+ | This is an 8 byte output buffer | ||
+ | |||
+ | === 9C31 === | ||
+ | This is an input buffer of undetermined length. Possibly 64 bytes. | ||
+ | |||
+ | === 9C75 === | ||
+ | A flag byte of some sort. Bits 5, 6, and 7 appear to be used. Bit 5 set means there's outgoing data in a control request (set report). Bit 5 reset means there's incoming data from a control request? Bit 6 reset might indicate that an 84P is connected as a peripheral, set might indicate a Vernier (or perhaps "other") peripheral. Bit seven set might indicate that a Set Address request was just received. | ||
+ | |||
+ | === 9C77 === | ||
+ | Used by the OS to hold the offset in the descriptor table of the descriptor to return. | ||
+ | |||
+ | === 9C78 === | ||
+ | Used by the OS to keep track of how many bytes it needs to send for USB device request replies. | ||
+ | |||
+ | === 9C79 === | ||
+ | Essentially a copy of Port 91. | ||
+ | |||
+ | == Flags == | ||
+ | Flag byte 41 appears to be the main USB flag. Bit 0 of byte 43 is also used for something related. | ||
+ | |||
+ | === 2,(iy+40) === | ||
+ | If this flag is set, the 82/83 page set might be used for data storage when reading from port A2. | ||
+ | |||
+ | === 0,(iy+41) === | ||
+ | If this flag is set, it will cause a certain part of USB code to abort. This is the code that is called from the interrupt routine when port 55h is 0Fh, and port 56h is 00h. This flag is set in an odd piece of code that loops around an output to port 0A2h. It reads the data to output, however, from RAM pages 02h and 03h. Will have to look into in more detail later. | ||
+ | |||
+ | === 2,(iy+41) === | ||
+ | This flag is set after loading the values of 9C16, 9C18, and 9C1A. But then it's reset if the VID/PID is 0451, E00F. *shrug* In BCALL 5254, it is reset after the bcall to 5290. This bit is checked in Mon, I think. | ||
+ | |||
+ | === 3,(iy+41) === | ||
+ | If set, this means the viewscreen adaptor is connected via USB and has been initialized. If this is set the BCALL 5290 will immediately terminate. Set in Init if device is E00F. At end of init, if flag is set, screen will turn on and be refreshed. | ||
+ | |||
+ | === 5,(iy+41) === | ||
+ | Reset somewhere in USB code. Not sure what it is. This bit is checked in Mon, I think. I think this means there's bulk data to be read. | ||
+ | |||
+ | === 6,(iy+41) === | ||
+ | Reset somewhere in USB code. Not sure what it is. | ||
+ | |||
+ | === 7,(iy+41) === | ||
+ | Reset somewhere in USB code. Not sure what it is. | ||
+ | |||
+ | == 84 as peripheral USB device requests == | ||
+ | This section describes the various USB commands that the calculator, acting as a peripheral, will accept. If the calculator receives commands that are not defined below, or if one of the checks designated as "makes sure" fails, it will set 9C84 to FF, and send a value of 60 out endpoint 0. NAK? Stall? | ||
+ | |||
+ | === Host to Device @ Device (0) === | ||
+ | These are commands in the host to device direction, with the device (as opposed to endpoint or interface) as the recipient. | ||
+ | |||
+ | ==== Clear Feature (1) ==== | ||
+ | When it receives a 0, 1 Clear Feature command, the calculator first makes sure that an address has been set (9C26 != 0). It also makes sure that the rest of the USB packet is not all zeros, for whatever reason. If processing is completed successfully, a value of 48 will be sent out port 91. WValues accepted as follows: | ||
+ | *1 - According to the USB spec this is Device Remote Wakeup. Sets 9C76 to 0. | ||
+ | *3 - Undefined according to USB spec, but this acts the same as 0,1,1 above. | ||
+ | *5 - Undefined according to USB spec, this makes sure 9C74 is zero, sets 9C73 to zero, and 9C75 to 1. | ||
+ | |||
+ | ==== Set Feature (3) ==== | ||
+ | When it receives a 3 Set Feature command, the calculator checks that the rest of the packet is not all zeros. It accepts the following wValues: | ||
+ | *1 - As per USB Spec, Sets Device Remote Wakeup. Sets 9C76 to 2 | ||
+ | *3 - Sets 9C73 to 1. | ||
+ | *4 - Sets 9C74 to 1. | ||
+ | *5 - Makes sure 9C74 is 0, and then sets 9C73 to 0 and 9C75 to 1. | ||
+ | |||
+ | ==== Set Address (5) ==== | ||
+ | Sets 9C86 to FF. Sets 9C71 to the received address value. (This will later be loaded to port 80). Sets bit 7 of 9C75 (which will indicate later to load the value to port 80). Outputs a value of 1 to port 5B. Outputs a value of 7F to port 87. | ||
+ | |||
+ | ==== Set Configuration (9) ==== | ||
+ | Makes sure the device is currently in the address or configured states. Accepts wValues as follows: | ||
+ | * 0 - This will return the device to the address state. Sets 9C26 appropriatly and then outputs 1 to port 5B and FF to port 87. | ||
+ | * 1 - Sets the calculator configuration 1, setting 9C26 appropriatly. Sets endpoint (8E) to 1, outputs 8 to port 90, 48 to port 91, 0 to port 92, 8 to port 93, 90 to port 94, and 0 to port 95. Then sets endpoint to 2, and repeats port outputs. | ||
+ | |||
+ | === Host to Device @ Endpoint (2) === | ||
+ | |||
+ | ==== Clear Feature (1) ==== | ||
+ | Clear halt? | ||
+ | |||
+ | ==== Set Feature (3) ==== | ||
+ | Set halt? | ||
+ | |||
+ | === Device @ Device to Host (80) === | ||
+ | |||
+ | ==== Get Status (0) ==== | ||
+ | Makes sure device is not in the default state. Makes sure packet data is not all zero (possibly with TIOS bug). Makes sure wLength is 2. If 9C76 is 2, responds with two bytes at offset of D5 from descriptor table. Otherwise responds with offset D6. The data seems to be 0,0 either way. | ||
+ | |||
+ | ==== Get Descriptor (6) ==== | ||
+ | Returns the requested descriptor. This is complicated. I'll fill in the details later. | ||
+ | |||
+ | ==== Get Configuration (8) ==== | ||
+ | Makes sure packet isn't all zeros. Makes sure wLength is 1. If currently in address state, returns 00. Otherwise returns 01. | ||
+ | |||
+ | === Device @ Interface to Host (81) === | ||
+ | |||
+ | ==== Get Status (0) ==== | ||
+ | Makes sure the device is not in the default state. Makes sure packet is not all zeros. Makes sure wIndex is 0 and wLength is 2. Responds with 0,0. | ||
+ | |||
+ | ==== Get Interface(A) ==== | ||
+ | I'm pretty sure this code is buggy, as it make sure that the device is in the default state, when it ought to be in the configured state. Anyway, after making sure of that and making sure wIndex and wLength are 1, it returns 0. | ||
+ | |||
+ | === Device @ Endpoint to Host (82) === | ||
+ | |||
+ | ==== Get Status (0) ==== | ||
+ | Details later... | ||
== In Other News == | == In Other News == | ||
− | * At some point, TI checks for USB devices VID: 045A, PID: | + | |
+ | === Stuff === | ||
+ | * At some point, TI checks for USB devices VID: 045A, PID: E003, E008, and E00F. It seems to return "ok" on E008 and E003, and error on E00F. E008 is the 84P SE. E003 is the 84P. No clue what E00F is. Perhaps the Viewscreen connector? | ||
* I have successfully connected my calculator and digital camera, and retrieved the Product ID and Vendor ID from the camera. Yay :) | * I have successfully connected my calculator and digital camera, and retrieved the Product ID and Vendor ID from the camera. Yay :) | ||
+ | * The EasyTemp is an HID device. Haven't figured out the protocol yet. | ||
+ | * For the ever curious: if you have both the serial and USB links connected, the calculator will choose to use the USB link. | ||
+ | * I don't know exactly how much current the calculator can provide, but it can definitely provide enough to power an optical mouse. I managed to turn the mouse on from the calculator, and everything seemed to work fine. | ||
+ | |||
+ | === Port Monitor === | ||
+ | I've written a [http://wikiti.denglend.net/stuff/portmon.8xk Port Monitor] that's been useful for figuring out what some of the ports do. It may be useful for others, but it's not extensively tested, so beware. "Setup Hook" records port data through the USB hook. "Setup Int" records data through an IM2 interrupt (will only take a new sample if a port in the requested range has changed). "Disable Mon" will Stop either the interrupt or hook monitor. "Exec Code" allows you to execute a BCALL or hex code, presumably while one of the monitors is running. Exec program isn't implemented yet. "View Data" allows you to view all the data by sample. "View Changes" allows you to view the data by port, only showing ports that had data changes. In future revisions I may add more monitor triggers through other hooks. Oh, it doesn't read from ports 82 or A0, as these will cause problems with USB activity. The interrupt doesn't read from ports 8C or 8D because these are just counter ports and throw off the sampling. | ||
+ | |||
+ | === Mouse === | ||
+ | So, I've successfully written an HID Mouse driver. One that, amazingly enough, actually works, with both corded and wireless optical mice. Video proof for disbelievers: [http://wikiti.denglend.net/stuff/mouse.avi mouse.avi (7MB)]. Source code will be going on SourceForge sometime in the near future. | ||
+ | |||
+ | === USB Protocol === | ||
+ | This PC<->calc (and presumably calc<->calc) USB protocol is vastly different than the serial protocol. A partial analysis of the protocol can be found [http://users.wpi.edu/~bmoody/usb.txt here]. | ||
+ | |||
+ | === Presentation Link === | ||
+ | The presentation link, conjectured to be the E00F device (and E00E for the 89 version) appears to request 16 byte packets? If someone can get ahold of one of these to confirm that, it would be wonderful. | ||
+ | |||
+ | === Tested Devices === | ||
+ | For device compatibility see the [[83Plus:Software:usb8x/Supported_Devices|appropriate page]] in the usb8x documentation. | ||
+ | |||
+ | === Alpha version driver available === | ||
+ | I've released an alpha version of [[83Plus:Software:usb8x|usb8x]], the TI-84 Plus USB driver, on sourceforge. Check out the project's [http://usb8x.sourceforge.net webpage] for downloads and more information. This version provides a host driver-layer for other applications and programs to use, and drivers for USB mouse, USB keyboard, TI's silverlink graphlink, Vernier Easy/Go devices, HID gamepads, and mass storage devices. Keep in mind this is an ALPHA version, and many things will probably change before the final release. In other words, don't release any programs that rely on the current driver-layer. | ||
+ | |||
+ | [[Category:83Plus:OS_Information|84 Plus USB Information]] |
Latest revision as of 15:34, 28 November 2010
- I moved this page from Talk:83Plus:BCALLs:5254 to here because it seems to fit better. Please note that this is still a work in progress, and don't take the information as gold. I figured having an option for a Talk page for this would outweigh the moving of it. For the time being, we'll leave the data formatted as-is, since it's still nicely done. --AndyJ 07:44, 27 May 2005 (PDT)
OK, I've started this talk page to post information about the 84 Plus USB. This isn't the ideal place, since not all of this stuff has to do with entry point 5254, but it'll have to do. If anyone else would like to contribute any information or thoughts, please do so. Much of this data has been discovered by analyzing how the EasyData application interacts with the EasyTemp probe. --Dan Englender 22:32, 23 May 2005 (PDT)
Many thanks to Olivier Armand for providing information invaluable to figuring out some of the harder to decipher USB ports. --Dan Englender 23:25, 9 Jul 2005 (PDT)
Contents
- 1 Easy Data
- 2 4087 Header
- 3 Hardware
- 3.1 Port 4C
- 3.2 Port 4D
- 3.3 Port 55
- 3.4 Port 56
- 3.5 Port 57
- 3.6 Port 5B
- 3.7 Port 80
- 3.8 Port 82
- 3.9 Port 83
- 3.10 Port 84
- 3.11 Port 85
- 3.12 Port 86
- 3.13 Port 87
- 3.14 Port 89
- 3.15 Port 8C
- 3.16 Port 8D
- 3.17 Port 8E
- 3.18 Port 8F
- 3.19 Port 90
- 3.20 Port 91
- 3.21 Port 93
- 3.22 Port 94
- 3.23 Port 96
- 3.24 Port 97
- 3.25 Port 98
- 3.26 Port 99
- 3.27 Port 9A
- 3.28 Port 9B
- 3.29 Port A0
- 3.30 Ports A1-A?
- 4 RAM
- 5 Flags
- 6 84 as peripheral USB device requests
- 7 In Other News
Easy Data
The USB entry points that Easy Data uses are:
5254 5257 525A 525D 5260
These routines return carry flag with an error code in A on failure, or no carry on success. On success they return BC=(9C16), DE=(9C1A), and HL=(9C18). 9C16 = Vendor ID. 9C18 = Device ID. 9C1A = ????.
The entry points seem to be called only on initialization and quit. On initialization 5254 then 525D are called, and then 525A six times. On quit, 5254, then 5260, then 5257 are called.
5254 BCALL
The 5254 entry point seems to take a callback address to be passed in A (page) and HL (address). That callback address appears to be called on quit, after 5257 is called.
5260 and 5257 BCALLs
The 5260 and 5257 entry points are called right after each other in the code, and don't seem to take any input. I guess they're some kind of USB shut down. 5260 doesn't do much of anything other than set 9C1E to 0000. 5257 plays with the ports some, and then clears the callback address. Since the call back address gets called, I'm assuming it must also call the callback address somewhere in there.
525A BCALL
525A takes a pointer to a structure in HL. 9C1C will be set to the structure pointer. Some checks on port 4C and 8F are done at teh beginning of this call. A data segment of value: 21 09 0002 0000 0800 will be sent through the control data port. This cooresponds to Host to Device's endpoint, vendor type, set configuration.
525D BCALL
525D takes a pointer to a structure in HL. The 525D entry point first checks to see if bit 3 of port 4C and bits 0 and 2 of port 8F are set. If they are not, it returns failure. These bits are not set by, say, plugging in the hardware. They are set, however, after 5254 has been called. After checking these bits, 9C1E is set to the passed structure pointer. If this value is zero, the routine will return failure. A value of 1 will be stored to HL+2, then a value of 1 will be output to port 8E, a value of 20h to port 94h, and success will be returned.
5290 BCALL
A BCALL to 5290 alone is enough to turn on the LED on EasyTemp. (Though it turns on to a strange orange color which is never seen during EasyData execution). It must do some sort of USB initialization type stuff. If bit 3,(iy+41) is set, 5290 will fail. So this must either be a USB-already-initialized flag, or a Don't-Use-USB flag I guess.
This BCALL appears to do the following:
- Do stuff
- Request the device descriptor with a maximum size of 8 bytes.
- Issue a Set Address Request, with an address of 2
- Request the device descriptor again, this time with a 18 byte maximum data size.
- Check device description for an appropriate TI or Vernier device and quit if not found.
- Do stuff
Why are there two device descriptor requests? Presumably so that the calculator can check the peripheral's max packet size (which is in the first 8 bytes), so that it will know how to segmentize further traffic.
5293 BCALL
This BCALL is enough to to turn the LED off on EasyTemp. It's called by 5260.
Other
The callback routine appears to recieve some kind of input in B. I'm not sure what yet.
I'm, err, not exactly clear at this point how the app actually gets the temperature data from the EasyTemp probe, as the entry point seem to only be called on init and quit. The callback routine seemed a likely candidate, but it's not that either. Maybe there's something going on in the interrupt that I'm not aware of. Or maybe there are some more entry points used that I missed. ------- I'm now pretty sure that EasyData gets data through the 9C1E structure's callback which I believe returns data retrieved from an interrupt transfer in the OS's interrupt.
EasyData is automatically started when you plug the EasyTemp into the USB port if: The current app is Home Screen, a program is not currently executing, and EasyTemp is loaded on the calculator. EasyTemp is searched for via the app header table below.
4087 Header
The calculator knows to run EasyData when the Probe is plugged in because it includes a special header at address 4087h. The format is as follows:
db 096h, 0E2h, 00h, 01h dw TablePtr ..... TablePtr: dw 1, TableEntryType, DataPtr ..... DataPtr: ;This is the EasyData data db 03h, 80h, 03h, 00h, 0F7h, 08h, 02h, 00h db 80h, 03h, 00h, 0F7h, 08h, 03h, 00h db 80h, 03h, 00h, 0F7h, 08h, 04h, 00h db 00h, 00h
In theory, the Table should be terminated with a 0000 word. It does not appear that EasyData does this.
Header Table Entries
The TableEntryType value can be one of the follow:
- 1 - This type is checked for in what seems to be unused OS code. There's a string "IsDevice" that is used in conjunction with it. Perhaps it's an unimplemented feature, or perhaps it's debug code that's not active in the release OS. Your guess is as good as mine.
- 2 - This is for the library functions used by OpenLib and ExecLib
- 3 - This is for the USB auto-launch, as used by EasyData
USB Data Table
If the TableEntryType is 3, then the data will be USB data and will be formatted as follows: The first byte will be the number of entries in the USB data table. Then, each entry, starts with a byte. Not sure what that is, but B_CALL 5269h returns it. Then comes a word. Not really sure what that is either. But weird things happen if the high byte is not 00. If the high byte is not 00, it will skip two bytes in the table for every bit set. If the low byte is 01, only the vendor ID will be checked, if it's 02, only the product ID will be checked (why?), if it's 03, the vendor ID and the product ID will be checked. If it's 04, the product revision is checked for being greater than the device's revision. If it's 08, the product revision is checked for being less than or equal to the device's revision. Depending on the low byte of this word, the words that follow will be (in order) the vendor ID, product ID, and the two device revisions to check against. If the low byte is 03, for example, then the next word will be the vendor ID, and the following word will be the product ID. If both of these match a connected USB device, then the app will launch.
FindSpecialAppHeader BCALL
The 50EF BCALL reads the 4087 Header. It is used by the OS. Returns SCF on failure, NC on success. On success, returns in HL the read table value. App name in OP1. Input DE is passed as the table entry to look for. Input A holds whether to look at certain app, or all apps. A = 0 means start at the first app, and search until you find an app with the appropriate header. A = 1 means start searching after the app in OP1. This would be used after the first success returned by A=0, to search the entire app list. A=2 means search only the app named in OP1.
5263 BCALL
The 5263 BCALL reads the 4087 Header. it is used by the OS. This appears to be very similar to the above entry point, except that it searches all the pages by number, instead of searching by name. Input DE = header type to find. Output C on failure, NC on success. HL = table entry value. (appSearchPage) = page it was found on. This only finds the first instance of the header type.
5266 BCALL
This allows you to continue a search you started with the 5263 BCALL. Input page in B.
5269 BCALL
The 5269 BCALL is used by the OS after determining that an app with the USB special app header exists. This entry point compares the values in the USB app header data table with the values at 9C16, 9C18, and 9C1A (vendor ID, product ID, and product revision, respectively). Input is HL -> data table, B = page. Returns Z if found, NZ if not found. Also returns first byte of vendor/product/revision ID entry in A. The full disassembly of this routine on OS 2.41 is here.
Hardware
Ports 55h and 56h are initially polled in the interrupt routine to determine USB activity. If activity is detected, 4Dh, 82h, 84h, 86h, 8Fh, 91h, and others may be polled as well.
Port 4C
Some sort of status port. Values of 1A or 5A and 12 or 52 mean something. Default value is 22. Some of the host routines make sure bit 3 is set.
Port 4D
Some sort of status port. Bit 4 is set if a type A cable is plugged in. The high nibble appears to be A if nothing is plugged in, and 6 while connected to the computer. The port is checked bit-wise, but I haven't quite figured out how the rest of the bits function yet. I'm as yet unsure whether the values of this port are set based on external events alone, or also influenced by stuff going on in the interrupt. Will check with interrupts disabled later. There is a routine that is called when the bit 1 port 56 event occurs which first waits for bit 6,4D to be reset (which seems like the standard condition after a peripheral has been plugged in). It then does some outputs to ports 3A, 39, 4C, and 8F; after which it waits for bit 6,4D to be set (which seems like the standard condition after a peripheral has been initialized). This doesn't exactly clarify what bit 6 actually means though.
Port 55
This port determines whether there's USB activity for the interrupt routine to take notice of. If any of the first five bits of the port are reset, that means something's happening in USB land.
- bit 0 - Not sure. Only seems to happen with peripheral.
- bit 1 - ???? (not checked by OS)
- bit 2 - Check port 56 for details on what event has happened
- bit 3 - ???? (not checked by OS)
- bit 4 - Data waiting? Or read for data? Or something like this.
Port 56
The default value for port 56h is 00. If bit 2 of port 55 is reset in the interrupt routine, this port should be checked to see what event occured. Each set bit indicates a particular event:
- bit 0 - I've seen this bit set while playing around, but the OS doesn't use it.
- bit 1 - Something to do with peripheral initialization?
- bit 2 - ??
- bit 3 - ??
- bit 4 - Plug-in, A-cable
- bit 5 - Unplug, A-cable
- bit 6 - Plug-in, B-cable
- bit 7 - Unplug, B-cable
Port 57
Sending 0 to this port seems to acknowledge USB interrupts.
Port 5B
I think if you load a value of 0 to this port, it will stop the USB controller from issuing interrupts to the calculator. Writing a value of 1 enables USB-related interrupts again.
Port 80
This input/output port holds the address for the device. Valid both when acting as peripheral and when acting as host. (Though the OS always assigns address 2 when acting as host.)
Port 82
Indicates outgoing data success. Seems to be valid both for data packets, and for IN/OUT tokens. Each bit indicates data sent successfully for that Ax port. It seems that the control port's bit registers for both incoming and outgoing data (instead of using port 84).
Port 83
I'm guessing that this is a continuation of port 82, with each bit indicating outgoing data success for endpoint/pipes A8 through AF.
Port 84
Indicates incoming data ready. Each bit indicates data ready to read on that Ax port. The control pipe acts as if it were an out pipe though, so don't expect to see bit 0 set. Check port 82 for control data.
Port 85
I'm guessing that this is a continuation of port 84, with each bit indicating incoming data ready for endpoint/pipes A8 through AF.
Port 86
Some sort of status port. Seems to generally hold a value of 0. Bits 5 or 7 being set seems to be an error condition. Other bits may or may not be error conditions, though it's beginning to look like they'll all errors or abort-conditions of some kind.
Port 87
This port might be a bitmap of which pipes in the Ax range are enabled for output. Port 88 would presumably be a continuation for pipes 8 through F.
Port 89
This port might be a bitmap of which pipes in the Ax range are enabled for input. Port 8A would presumably be a continuation for pipes 8 through F.
Port 8C
The low byte of the 15-bit frame counter. It is automatically incremented if a cable is plugged in. I haven't timed it, but in theory it should be incremented about once per millisecond.
Port 8D
The high byte of the 15-bit frame counter. See port 8C.
Port 8E
This input/output port designates current endpoint to read from/transfer to. Can be 0-15.
Port 8F
Values of 1 or 3 are outputted to this port. I have no clue what they mean. After USB init, on read, it seems to be some sort of status. Bit 2 being set appears to imply calculator-as-host, reset seems to imply calculator-as-peripheral. Bit 3 set appears to mean B device, and reset means A device.
Port 90
This port sets up the maximum packet size of outgoing pipes. See port 93.
Port 91
This is the outgoing pipe command port. Port 82h seems to indicate when the command is ready. These bit values are valid in host mode on the control pipe, at least:
- bit 1 - set indicates command in host to device direction, reset indicates from device to host
- bit 3 - set means output data as SETUP packet/token?
- bit 5 - set means output IN token? Reset means OUT token? (compliment of bit 1?)
- bit 6 - reset means there is data associated with this command
So commands for the control pipe would look like:
- Send Control Command (no data)
- Output SETUP data to port A0
- Output 0A to port 91 (setup token/data from host to device)
- Output 60 to port 91 (go to status stage)
- Send Control Command (with incoming data)
- Output SETUP data to port A0
- Output 0A to port 91 (setup token/data from host to device)
- Output 20 to port 91 (request IN data)
- Read data from port A0
- Output 42 to port 91 (go to status stage)
- SendControl Command (with outgoing data)
- Output SETUP data to port A0
- Output 0A to port 91 (setup token/data from host to device)
- Output data to port A0
- Output 02 to port 91 (OUT data)
- Output 60 to port 91 (go to status stage)
On read, bits 2 or 4 being set indicate an error state. Bit 2 is stall, bit 4 is NAK.
Port 93
This port sets up the maximum packet size for incoming pipes. Multiply the value of the port by 8 to get the packet size. You should probably only set one bit. I have no clue what would happen if you set more than one.
Port 94
This is the incoming pipe command port. Similar to port 91.
Port 96
Holds the low byte of the size of the received and buffered input data for the currently selected endpoint/pipe. Read the data from the appropriate Ax port.
Port 97
Presumably holds the high byte of the size of the received and buffered input data fro the currently selected endpoint/pipe. The 84P doesn't actually send any packets larger than 256 bytes, so it's not used.
Port 98
If the description of port 9A is even remotely right, then this port has a good chance of being the same thing, but for outgoing pipes.
Port 99
While I'm making things up, if ports 98, 9A, and 9B are all correct, then maybe this is the interrupt interval for setup of outgoing interrupt pipes and 9B is incoming interrupt pipes. *shrug*
Port 9A
OK, this is quite a strech, long shot, guess, etc; but here are some possibilities for this port: This might set up incoming pipes. The high nibble might define the type of pipe. 2 would be bulk, and 3 would be interrupt. That might make 1 isochronous, but I'm not going to go there. The low nibble might be which pipe to map the current endpoint to. This cooresponds to the port in the AX range. So 21 would map an incoming bulk pipe to port A1h. Or, that could all be completely nonsense.
Port 9B
This might setup the poll interval for an interrupt endpoint. Or it might not. Just a thought.
Port A0
This is the control pipe data I/O port. I'm not sure if it's statically fixed this way, or if it is configured like the other pipes.
Ports A1-A?
Ports A1 and A2 are used by the OS as data I/O pipes and are set up via port 98 or 9A. It seems likely that more ports in the Ax range can be used as pipes, and I'm guessing all the ports A0-AF can be used.
RAM
9C13/9C14
9C13 is the page, and 9C14 is the address of a callback routine. It is set by the 5254 BCALL, and called at various times. I'm not really sure what the callback routine is for yet.
9C16
This is where the vendor ID is stored. It is populated by at least the 5290 BCALL, and perhaps others.
9C18
This is where the product ID is stored. It is populated by at least the 5290 BCALL, and perhaps others.
9C1A
This is where the device release number is stored. It is populated by at least the 5290 BCALL, and perhaps others.
9C1C
A pointer to another structure. Similar to 9C1E. Output control transfers?
9C1E
A pointer to some sort of structure. First word of structure is a pointer to some sort of receive buffer. Reads from port A1 may be stored here. Perhaps for interrupt transfers? Offset 2 of structure is a byte value. Offset 3 of structure is a callback page and address
9C26
Byte value representing device state (calc as peripheral)
- 0 = Device in default state
- 1 = Device in addressed state
- 2 = Device in configured state
9C27
Another byte denoting something about the current state or operation. A value of 1 might imply a host->periph communication and a value of 2 might imply a periph->host communication.
9C28
Current USB status, or something like that.
- 1 = in the middle of USB host initialization
- 2 = Background intialization complete?
- 3 = Explicit (5290) initialization complete?
- 4 =????
- 5 = Something to do with uninit?
- 6 = Something to do with error states?
9C29
This is an 8 byte output buffer
9C31
This is an input buffer of undetermined length. Possibly 64 bytes.
9C75
A flag byte of some sort. Bits 5, 6, and 7 appear to be used. Bit 5 set means there's outgoing data in a control request (set report). Bit 5 reset means there's incoming data from a control request? Bit 6 reset might indicate that an 84P is connected as a peripheral, set might indicate a Vernier (or perhaps "other") peripheral. Bit seven set might indicate that a Set Address request was just received.
9C77
Used by the OS to hold the offset in the descriptor table of the descriptor to return.
9C78
Used by the OS to keep track of how many bytes it needs to send for USB device request replies.
9C79
Essentially a copy of Port 91.
Flags
Flag byte 41 appears to be the main USB flag. Bit 0 of byte 43 is also used for something related.
2,(iy+40)
If this flag is set, the 82/83 page set might be used for data storage when reading from port A2.
0,(iy+41)
If this flag is set, it will cause a certain part of USB code to abort. This is the code that is called from the interrupt routine when port 55h is 0Fh, and port 56h is 00h. This flag is set in an odd piece of code that loops around an output to port 0A2h. It reads the data to output, however, from RAM pages 02h and 03h. Will have to look into in more detail later.
2,(iy+41)
This flag is set after loading the values of 9C16, 9C18, and 9C1A. But then it's reset if the VID/PID is 0451, E00F. *shrug* In BCALL 5254, it is reset after the bcall to 5290. This bit is checked in Mon, I think.
3,(iy+41)
If set, this means the viewscreen adaptor is connected via USB and has been initialized. If this is set the BCALL 5290 will immediately terminate. Set in Init if device is E00F. At end of init, if flag is set, screen will turn on and be refreshed.
5,(iy+41)
Reset somewhere in USB code. Not sure what it is. This bit is checked in Mon, I think. I think this means there's bulk data to be read.
6,(iy+41)
Reset somewhere in USB code. Not sure what it is.
7,(iy+41)
Reset somewhere in USB code. Not sure what it is.
84 as peripheral USB device requests
This section describes the various USB commands that the calculator, acting as a peripheral, will accept. If the calculator receives commands that are not defined below, or if one of the checks designated as "makes sure" fails, it will set 9C84 to FF, and send a value of 60 out endpoint 0. NAK? Stall?
Host to Device @ Device (0)
These are commands in the host to device direction, with the device (as opposed to endpoint or interface) as the recipient.
Clear Feature (1)
When it receives a 0, 1 Clear Feature command, the calculator first makes sure that an address has been set (9C26 != 0). It also makes sure that the rest of the USB packet is not all zeros, for whatever reason. If processing is completed successfully, a value of 48 will be sent out port 91. WValues accepted as follows:
- 1 - According to the USB spec this is Device Remote Wakeup. Sets 9C76 to 0.
- 3 - Undefined according to USB spec, but this acts the same as 0,1,1 above.
- 5 - Undefined according to USB spec, this makes sure 9C74 is zero, sets 9C73 to zero, and 9C75 to 1.
Set Feature (3)
When it receives a 3 Set Feature command, the calculator checks that the rest of the packet is not all zeros. It accepts the following wValues:
- 1 - As per USB Spec, Sets Device Remote Wakeup. Sets 9C76 to 2
- 3 - Sets 9C73 to 1.
- 4 - Sets 9C74 to 1.
- 5 - Makes sure 9C74 is 0, and then sets 9C73 to 0 and 9C75 to 1.
Set Address (5)
Sets 9C86 to FF. Sets 9C71 to the received address value. (This will later be loaded to port 80). Sets bit 7 of 9C75 (which will indicate later to load the value to port 80). Outputs a value of 1 to port 5B. Outputs a value of 7F to port 87.
Set Configuration (9)
Makes sure the device is currently in the address or configured states. Accepts wValues as follows:
- 0 - This will return the device to the address state. Sets 9C26 appropriatly and then outputs 1 to port 5B and FF to port 87.
- 1 - Sets the calculator configuration 1, setting 9C26 appropriatly. Sets endpoint (8E) to 1, outputs 8 to port 90, 48 to port 91, 0 to port 92, 8 to port 93, 90 to port 94, and 0 to port 95. Then sets endpoint to 2, and repeats port outputs.
Host to Device @ Endpoint (2)
Clear Feature (1)
Clear halt?
Set Feature (3)
Set halt?
Device @ Device to Host (80)
Get Status (0)
Makes sure device is not in the default state. Makes sure packet data is not all zero (possibly with TIOS bug). Makes sure wLength is 2. If 9C76 is 2, responds with two bytes at offset of D5 from descriptor table. Otherwise responds with offset D6. The data seems to be 0,0 either way.
Get Descriptor (6)
Returns the requested descriptor. This is complicated. I'll fill in the details later.
Get Configuration (8)
Makes sure packet isn't all zeros. Makes sure wLength is 1. If currently in address state, returns 00. Otherwise returns 01.
Device @ Interface to Host (81)
Get Status (0)
Makes sure the device is not in the default state. Makes sure packet is not all zeros. Makes sure wIndex is 0 and wLength is 2. Responds with 0,0.
Get Interface(A)
I'm pretty sure this code is buggy, as it make sure that the device is in the default state, when it ought to be in the configured state. Anyway, after making sure of that and making sure wIndex and wLength are 1, it returns 0.
Device @ Endpoint to Host (82)
Get Status (0)
Details later...
In Other News
Stuff
- At some point, TI checks for USB devices VID: 045A, PID: E003, E008, and E00F. It seems to return "ok" on E008 and E003, and error on E00F. E008 is the 84P SE. E003 is the 84P. No clue what E00F is. Perhaps the Viewscreen connector?
- I have successfully connected my calculator and digital camera, and retrieved the Product ID and Vendor ID from the camera. Yay :)
- The EasyTemp is an HID device. Haven't figured out the protocol yet.
- For the ever curious: if you have both the serial and USB links connected, the calculator will choose to use the USB link.
- I don't know exactly how much current the calculator can provide, but it can definitely provide enough to power an optical mouse. I managed to turn the mouse on from the calculator, and everything seemed to work fine.
Port Monitor
I've written a Port Monitor that's been useful for figuring out what some of the ports do. It may be useful for others, but it's not extensively tested, so beware. "Setup Hook" records port data through the USB hook. "Setup Int" records data through an IM2 interrupt (will only take a new sample if a port in the requested range has changed). "Disable Mon" will Stop either the interrupt or hook monitor. "Exec Code" allows you to execute a BCALL or hex code, presumably while one of the monitors is running. Exec program isn't implemented yet. "View Data" allows you to view all the data by sample. "View Changes" allows you to view the data by port, only showing ports that had data changes. In future revisions I may add more monitor triggers through other hooks. Oh, it doesn't read from ports 82 or A0, as these will cause problems with USB activity. The interrupt doesn't read from ports 8C or 8D because these are just counter ports and throw off the sampling.
Mouse
So, I've successfully written an HID Mouse driver. One that, amazingly enough, actually works, with both corded and wireless optical mice. Video proof for disbelievers: mouse.avi (7MB). Source code will be going on SourceForge sometime in the near future.
USB Protocol
This PC<->calc (and presumably calc<->calc) USB protocol is vastly different than the serial protocol. A partial analysis of the protocol can be found here.
Presentation Link
The presentation link, conjectured to be the E00F device (and E00E for the 89 version) appears to request 16 byte packets? If someone can get ahold of one of these to confirm that, it would be wonderful.
Tested Devices
For device compatibility see the appropriate page in the usb8x documentation.
Alpha version driver available
I've released an alpha version of usb8x, the TI-84 Plus USB driver, on sourceforge. Check out the project's webpage for downloads and more information. This version provides a host driver-layer for other applications and programs to use, and drivers for USB mouse, USB keyboard, TI's silverlink graphlink, Vernier Easy/Go devices, HID gamepads, and mass storage devices. Keep in mind this is an ALPHA version, and many things will probably change before the final release. In other words, don't release any programs that rely on the current driver-layer.