Tuesday, March 24, 2009

The Hierarchical Concepts of USB

Although I've built some USB related products, I still get confused with some concepts about USB, esp. that ubiquitous word of "setup". Taking the time of re-writing a STMicroelectronics ST7 Tube driver to WinUSB, I sorted the concepts out in case I am lost again.

USB communications are categorized into 4 kinds of TRANSACTIONS, namely,
- Control Transfers
- Interrupt Transfers
- Isochronous Transfers
- Bulk Transfers

Each TRANSACTION is made up of raw PACKETS:
- a Token Packet (Header defining what it expects to follow),
- an Optional Data Packet, (Containing the payload) and a
- a Status Packet (Used to acknowledge transactions and to provide a means of error correction)


Each Packet is a combination of 5 FIELDS:
- Sync : Synchronising clocks
- PID : Packet ID
- ADDR : Device Address
- ENDP : Endpoit on thhis Device
- CRC
- EOP : End of Packet

And the combination is NOT random, actually only 4 of them:
- Token Packets = Sync + PID + ADDR + ENDP + CRC5 + EOP
- Data Packets = Sync + PID + Data + CRC16 + EOP
- Handshake Packets = Sync + PID + EOP
- Start of Frame Packets = Sync + PID + Frame Number + CRC5 + EOP

Sepcial notes about "SETUP":

There is a kind of PID named SETUP amongst other types such as IN and OUT, only a Token Packets has a SETUP PID.

A Token Packet with the PID being SETUP can only appear in Control Transfers, and only in the SETUP STAGE.

Control Transfers have 3 stages: SETUP, DATA, and STATUS stages. In the latter 2 stages, no Token Packets with PID being SETUP would appear. only Token Packets with PID being IN or OUT, followed by Data Packets are used.

SETUP PACKETS are packets that are sent through Control Transfers. They cover packets in all the 3 stages aforementioned, but not only the Token Packets with PID being SETUP.

SETUP PACKETS are so called because they are used to set up the device including the detection and configuration of the device and carrying out common functions such as setting the USB device’s address, requesting a device descriptor or checking the status of a endpoint. Hence the concept of STANDARD REQUESTS, namely,
STANDARD DEVICE REQUESTS:
- get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
set_address(0x05)
get_descriptor(0x06)
set_descriptor(0x07)
get_configuration(0x08)
set_configuration(0x09)

- STANDARD INTERFACE REQUESTS:
get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
get_interface(0x0a)
set_interface(0x11)

- STANDARD ENDPOINT REQUESTS:
get_status(0x00)
clear_feature(0x01)
set_feature(0x03)
synch_frame(0x12)


While writting software on the Host(e.g. PC), SETUP PACKETS are wrapped into data structs such as WINUSB_SETUP_PACKET in WinUSB, which correspond to the whole 3-stage Control Transfers, not the SETUP STAGE, neither the token packets with PID being SETUP.

this USB-in-a-nutshell is the best USB tutorial online and where the above info are extracted from.

Get Current Time in C++

The ATL/MFC way:
/*Output Current Time is: 03/24/09 15:54:43*/



#include <atltime.h> // for CTime

#include <atlstr.h> // for CString

#include <iostream>



int main()

{

CString s(CTime::GetCurrentTime().Format("%c"));

std::wcout << L"Current Time is: "<< s.GetString();

}







The Boost Way:

/* Uses the clock to get the local time

*

* Expected Output something like:

* 2002-Mar-08 16:30:59

*/



#include "boost/date_time/posix_time/posix_time.hpp"

#include <iostream>



int main()

{

using namespace boost::posix_time;

using namespace boost::gregorian;



//get the current time from the clock -- one second resolution

ptime now = second_clock::local_time();



std::cout << L"Current Time is: "

<< to_simple_wstring(now)

<< std::endl;

return 0;

}