DRAFT 2014-12-24 Introduction ============ The LWWire protocol is based on the Drivewire protocol originally created by Boisy Pitre and later expanded by others including Aaron Wolfe. The original Drivewire protocol was very simple. It has since acquired quite a few bits and bobs that have unfortunate semantics. Further, Over the years, Drivewire has accumulated quite a few features which it is not possible for the client to reliably detect support for. In addition, the protocol seems to be ever expanding and accumulating features of limited utility. The goal of LWWire is to provide a stable core protocol that returns to the roots of Drivewire 3. The core protocol will support extension negotiation which allows the client to request specific additional features. This negotiation must occur before the features can be used. A secondary goal is for a basic Drivewire client to be able to perform block I/O on virtual drives even if it does not support the advanced negotiation. The Protocol ============ Throughout the protocol discussion, the term client will refer to the device being served, usually a Coco an emulator of some sort. The term server will refer to the software running on a PC or other similar device that answers requests from the client. The LWWire protocol is a master-slave protocol with the client serving the role of the master. This seems like a reversal but it is necessary because the client will usually be the device with limited resources which cannot reliably respond to a byte appearing on the communication channel. Thus, all transactions are initiated by the client. All values greater than a single octet are represented in network byte order, which is otherwise known as big endian. The protocol is octet based. The first octet of any request is an operation code. This operation code completely defines the request. Further data may follow the operation code, depending on the specifc operation. Some operations may require further round trips as well. There are two possible types of response from the server. The first is a standard fixed length response which is defined by the particular operation. However, an operation may further define that it returns a variable length packet. Such a packet is prefixed by a 16 bit length followed by the actual data. Where such a packet is described, the header is not included in the description. The variable length return values should be avoided except when there is a true benefit to using them. Such a use might be passing along an IP packet, for instance. When a client comes online, it must send a "DWINIT" operation. The driver version/identifier value is not specified by the protocol and must not change the behaviour of the server. The server will then respond with its version number. If that number is anything other 0x80, the client must assume the server is NOT LWWire. If it receives no response, it may continue with the notion that it might be a Drivewire 3 server. If the client does receive an indicator that it is talking to LWWire, and it wishes to use anything other than requests in the Base protocol (anyting in the "Base Protocol" section below), it MUST initiate a feature negotiation request and it MUST NOT initiate any usage of the requested feature unless it receives an ACK response from the server. If the delay between subsequent bytes in a request is greater 100 milliseconds, the server MUST assume the transaction has failed and treat it as an unknown transaction. The client MUST implement a similar timeout to prevent entering into an infinite loop waiting for octets that may never come. The timeout on the client must be no longer than 1000 milliseconds and should be no shorter than 100 milliseconds. These timeouts MUST be applied to ALL octets that are part of the communication stream. Notwithstanding the above, some operations may specify a longer timeout which must be respected by that operation. If the server receives an unknown request OR it detects a timeout receiving a request, it MUST abort any ongoing request. It MUST then remain silent for at least 1100 milliseconds to force a timeout on the client. The server MAY choose to change it's port speed parameters if it detects that the request may be valid but there is a transmission speed mismatch. This behaviour MUST NOT be relied upon by the client. Protocol Operations =================== Each operation is formatted with a header indicating the operation code in hexadecimal following by it's name. Below that is the specification of the actual request in a table organized by offset within the request. The table may be absent if the request consists of nothing but the operation code. Below that is prose describing the operation. Base Protocol ------------- The base protocol is always active. It is basically the old Drivewire 3 protocol with no support for wirebug, which turns out to be useful mostly on paper rather than in real circumstances. Operations are listed in numerical order. 00 NOOP This request is a "no-op". The server MUST ignore it and not treat it as an error. 23 TIME This request instructs the server to respond with its current date and time. The response looks as follows: Octet Meaning ----- ------- 0 years since 1900 1 month (1-12) 2 day (1-31) 3 hour (0-23) 4 minute (0-59) 5 second (0-60) 6 day of week (0-6, 0 = Sunday) This packet roughly corresponds to the return structure for the localtime() function in C. Note that this request is part of the original Drivewire 3 specification. However, Drivewire 3 specifies only 0-59 for the seconds value. LWWire allows the value 60 for the seconds value for the rare case where a leap second is in effect. This is unlikely to ever be a problem in real deployments since leap seconds can occur at most four times per year. 46 PRINTFLUSH This operation tells the server to flush its print buffer to its defined printer or analogue. If it does not support a printer or analogue, or there is no data to flush, this operation does nothing. 47 GETSTAT Octet Meaning ----- ------- 0 operation code 1 drive number 2 GetStat or SetStat code This operations are specified for compatibility with Drivewire. There is no response defined. It SHOULD be treated the same as NOOP. The server MAY choose to log this request but is not required to. 49 INIT This indicates the server MUST switch to Drivewire 3 mode (if it has one) or, if it doesn't, switch to Base Protocol mode by disabling all extensions. It must also clear any statistics counters and state set by any previous operations. 50 PRINT Octet Meaning ----- ------- 0 operation code 1 print data octet This request tells the server to queue the specified print data octet for output to a printer or some analogue supported by the server. If the server does not support printing, it will simply ignore this request. The server MAY choose to flush the print buffer to its printer or analogue at any time, say because it has not received additional data for some time. The precise mechanism to do this is not specifically defined. 52 READ NOTE: this operation should not be used unless a buffered I/O channel of some kind is in use. Because the client must read the first response byte and then decide whether to read 258 further bytes, it is a good idea for the server to introduce a short delay after the result code, say the length of a single octet transmission. It is strongly recommended that the READEX operation be used instead. This operation is supported for compatibility with old Drivewire implementations. Octet Meaning 0 operation code 1 drive number 2-4 LSN requested This operation requests the server to read a sector from a specified drive. In the event of an error, this operation will return a nonzero error code (see the "Error Codes" section below). In the event of success, the response will look as follows: Octet Meaning 0 00 1-2 16 bit checksum (simple sum) 3-258 sector data If the checksum of the received data does not match, the client may choose to retry with the REREAD operation. The server may choose to treat REREAD as an alias of READ or it may treat a REREAD without a previous matching READ as an error. 53 SETSTAT Octet Meaning ----- ------- 0 operation code 1 drive number 2 GetStat or SetStat code This operation is specified for compatibility with Drivewire. There is no response defined. It SHOULD be treated the same as NOOP. The server MAY choose to log this request but is not required to. 54 TERM This request indicates the client is finished with the protocol. It should be treated the same as INIT (49). It is only specified here for compatibility with the old Drivewire 3 protocol. New client implementations should not use this operation. 57 WRITE Octet Meaning ----- ------- 0 operation code 1 drive number 2-4 24 bit LSN 5-260 sector data 261-262 16 bit checksum This operation tells the server to write the specified sector data to the specified LSN on the specified drive. Before doing the write, however, the server will verify the checksum (simple sum of sector octets) and if it fails, it will not write the sector and return the appropriate error code. Otherwise, it will attempt the write and return an error code if appropriate. The error codes are listed in the "Error Codes" section below. The response to this transaction is a single octet indicating success (00) or failure (error code). On a checksum error, the client may choose to retry with the REWRITE operation. On other errors, retrying does not make sense as the error condition is unlikely to go away. The server may choose to treat REWRITE as an alias of WRITE. It may also choose to treat a REWRITE in the absence of a matching WRITE immediately prior as an error. The client is not obligated to use the REWRITE operation ever. 5A DWINIT Octet Meaning ----- ------- 0 5A (opcode) 1 driver version The driver version above may be a value assigned by the Drivewire maintainer. However, LWWire does not treat any values specially. Upon receiving this operation, the server must disable any extensions and enter into Base Protocol mode. It must also clear any statistics counters and state set by any previous operations. The server will respond with the following packet: Octet Meaning ----- ------- 0 server identifier The server identifier received will be 0x80 if the server supports the LWWire protocol. If it is anything other than 0x80, the client MUST assume that the server is NOT LWWire and take whatever action it deems appropriate, which may include falling back to Drivewire mode. 72 REREAD See 52 READ. 77 REWRITE See 57 WRITE. D2 READEX Octet Meaning ----- ------- 0 operation code 1 drive number 2-4 24 bit LSN The READEX operation requests the server to read the logical sector specified by the LSN from the specified drive. The server will respond with 256 bytes of data. In the event that an error occured, it will respond with 256 NUL bytes. Otherwise, it will respond with the actual sector data. The client will calculate a 16 bit checksum which is a simple sum of all bytes received. It will then send that checksum to the server. The server must permit a longer timeout waiting for the checksum than is otherwise expected to give the remote side long enough to actually calculate the checksum. It is recommended that the timeout here be at least 200ms. Upon receipt of the checksum, the server will verify that it is correct. If there was an error reading the sector OR the checksum does not match, the server will return one of the error codes in the "Error Codes" section below. Otherwise it will return a NUL byte. In the event of a checksum error, the client may retry the read. Other errors are unlikely to go away on a retry so retrying in those cases is not recommended. The REREADEX request follows an identical flow. The server MAY choose to treat a REREADEX operation without an immediately preceding READEX operation as an error. It may choose to avoid re-reading the sector data from the backing store on the server if it has already read the same LSN for a previous READEX operation. However, it is also acceptable to simply treat this as an alias for READEX. F0 REQUESTEXTENSION Octet Meaning 0 operation code 1 extension code (8 bits) This request is used to request a specific extension, as specified by the extension code. The server will respond with an ACK response (0x42) or a NAK response (0x55). Any other response must be considered an error and the client MUST re-initialize its driver and perform the DWINIT handshake again. That includes in the case of a timeout. A NAK means the server does not support the requested extension OR it is unwilling to make it available for whatever reason. An ACK means the server has enabled the requested extension for this particular client. See the section "Extension Codes" for a list of extension codes. F1 DISABLEEXTENSION Octet Meaning 0 operation code 1 extension code This request is used to request that the server discontinue usage of a specific extension. The server will respond with an ACK (0x42) if it is able to discontinue the extension. This is the normal response. Some extensions may not be disablable (which will be specified in the extension specification). In this case, the server will respond with a NAK (0x55). In the event of a NAK, the client may choose to continue with the extension enabled. It may also choose to treat that as an error condition and re-initiate the DWINIT handshake which will forcibly disable all extensions. Requesting to disable an extension that is not enabled is not considered an error since it doesn't require changing the state of anything. In that case, the ACK response is correct. See the section "Extension Codes" for a list of extension codes. F2 REREADEX See D2 READEX. F3 EXTENSIONOP This request indicates that the request is associated with a specific extension. The second octet is the extension number. Everything after that is defined entirely by the specified extension. If the specified extension is not enabled, this request MUST be treated as an unknown request. The server MUST NOT send a response to any request for any extension that is not currently active. This mechanism is provided so that extensions can provide their own operations without having to select operation codes from the global pool. Codes can only be assigned in the global pool by the LWWire maintainer. Codes used inside this request structure can be arbitrarily defined by the extension without any coordination. F8 RESET3 FE RESET1 FF RESET2 Either one of these operations should be treated as though the client has gone away or restarted. These MUST be treated exactly like the INIT (49) operation. Error Codes =========== Code Meaning ---- ------- 00 No error, checksum OK F3 checksum error F4 read error (out of bounds, underlying I/O error) F5 write error F6 not ready (invalid drive, etc) Extension Codes =============== Any code not otherwise listed below is reserved. If you wish to have an official extension code assigned, contact the maintainer of LWWire to request one. If you are working on something that does not need general distribution, or which is only experimental, consider using the private range listed below. 00 VPORT 01 PACKET E0-EF reserved for future extension code expansion F0-FF reserved for private extensions and will never be assigned