먼저 USB는 4가지 전송타입이 있는데, 그중에 Endpoint 0 는 'Control Transfer' 전송 방법을 사용하죠. 'Control Transfer'는 3가지 'Sequence'가 있는데, 'Control Write', 'Control Read', 'No-data Control'가 있습니다.
'Control Read'를 예로 들어 보죠. 'Control Read'는 아래와 같은 프로시져로 패킷이 전송됩니다.
루트 허브에 USB 디바이스를 꼽으면, 먼저 호스트에서 'Setup(0)'가 내려 옵니다. 그럼 다시 'Setup(0)'의 구성을 볼까요!!
'Setup' - 'Data(0)' - 'ACK'의 세가지 토큰으로 구성되어 있죠. 'Setup'은 호스트가 내려보내 주는 토큰이고, 'Data(0)'도 호스트가 내려보내 주는 토큰 '80 06 00 01 00 00 40 00'으로 'Get Descriptor'라고 하는 놈의 'Request'입니다. 'ACK'는 당연히 디바이스가 올려보내 주는 것이 겠죠.
그럼 'In(1)'에 대해서 보면,
'In' - 'Data(1)' - 'ACK'죠..당연 'In'은 호스트가 내려보내 주는 토큰이죠. 아주 당연한 얘기죠. 'Get Descriptor'라는 'Request'를 내려보내줬으니까 디바이스로부터 'Descriptor' 정보를 가져와야 되겠죠. 그럼 디바이스는 'Data(1)'에 '12 01 00 01 00 00 00 08'을 호스트로 보내겠죠. 이 데이터는 디바이스에 따라 다릅니다. 자 그러면 호스트는 'Data(1)'을 받았으니까 'ACK'로 응답을 해주겠죠.
이런 인련의 과정으로 통신을 하죠.
그리고 Endpoint0로 In 토큰이나 Out 토큰으로 내려 올때 디바이스는 'ACK'를 할건가 'NAK'를 할 건가 'STALL'을 할 건가 의 기로에 있는데, 이것은 해당 레지스터의 모드를 선택함으로써 수행할 수 있는데, 님의 말처럼 분명하게 할 수 는 없습니다. 왜냐하면 F/W에서 처리해야하는게 아니라 SIE(Serial Interface Engine)에서 하드웨어적으로 처리가 된다는 말입니다. 모드 중에서 가장 근접한 놈을 찾아서 세팅해 주면 되죠. 대부분의 칩들로 마찬가지 일겁니다.