본 글은 외장 모니터의 EDID를 읽어서 정상인 경우에만 연결하지 않고, 무조건 연결하는 방법에 대한 것입니다.

 

외장 모니터(HDMI)를 잘 쓰다가, 갑자기 연결이 되지 않는 문제가 발생했습니다.

 

xrandr 명령어를 이용하면 HDMI가 연결되지 않았습니다.

$ xrandr
...
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
DP-2 disconnected (normal left inverted right x axis y axis)
HDMI-2 disconnected (normal left inverted right x axis y axis)

dmesg로 확인해 보니 아래와 같은 메시지를 확인할 수 있었습니다.

[00] BAD  00 ff ff ff ff ff ff 00 05 e3 53 23 ec 02 00 00
[00] BAD  28 15 01 03 80 33 1d 78 2a 6e 95 a3 54 4f 9f 26
[00] BAD  00 50 54 bf ef 00 d1 c0 b3 00 95 00 81 80 81 40
[00] BAD  81 c0 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
[00] BAD  45 00 fd 1e 11 00 00 1e 00 00 00 fd 00 32 4c 1e
[00] BAD  53 11 00 0a 20 20 20 20 20 20 00 00 00 fc 00 32
[00] BAD  33 35 33 0a 20 20 20 20 20 20 20 20 00 00 00 ff
[00] BAD  00 41 49 4a 42 41 4f 41 30 30 30 37 34 38 01 05

때로는 메시지 위에 "EDID is invalid:"라는 메시지가 보이기도 했습니다.

 

EDID(위키피디아)는 모니터 정보를 PC에 전달하는 것으로, 결론적으로 EDID 에러 때문에 PC가 외장 모니터를 인식하지 못하는 이슈입니다.

EDID는 EEPROM에 저장되는데 문제가 발생하기도 하는 것 같습니다. - "Some people say hot-plugging the cables can cause corruption."(링크 1)

링크 2를 참고해서, 아래 명령을 실행했지만 edid.bin이 생성되지 않았습니다. (read-edid edid-decode 설치 후 실행)

$ sudo get-edid -m 0 > edid.bin

그래서, 앞서 dmesg로 확인한 EDID를 c 프로그램을 이용해서 binary 파일(edid.bin)을 생성하고 아래 명령을 수행해 보았습니다.

$ parse-edid < edid.bin
Partial Read... Try again

EDID는 256 bytes 인데, 128 bytes만 변환해서 나오는 에러입니다. 나머지 128 bytes를 모두 0으로 채워서 edid.bin을 생성한 후 명령어를 실행하면,

$ parse-edid < edid.bin
WARNING: Checksum failed
Trying to continue...
Section "Monitor"
...

모니터에 대한 정보는 잘 나오는데, Checksum에러가 발생한 것을 확인할 수 있었습니다.

다시 아래 명령을 실행하면,

$ cat edid.bin | edid-decode
edid-decode (hex):
...
Has 1 extension block
Checksum: 0x5 (should be 0x16)
...

Checksum이 원래 0x16이어야 하는데 0x5로 잘못되었다는 내용을 확인할 수 있습니다.

위키피디아를 확인하면 Checksum의 위치는 128 bytes의 맨 마지막 byte입니다.

이를 0x05 -> 0x16으로 변경 후 edid.bin을 새로 생성해서 위 명령들을 수행하면 정상적으로 수행되는 것을 확인할 수 있었습니다.

 

결론적으로 외부 모니터로부터 EDID를 읽었는데 Checksum이 틀려서 발생하는 문제였습니다.

 

링크 3을 참조하면, edid.bin 파일은 /lib/firmware/에 위치하는 것으로 보입니다. 그래서 아래 명령어로 edid.bin을 복사했습니다.

$ cp edid.bin /lib/firmware/edid.bin

그리고 링크 2를 참고해서 grub을 변경했습니다.

$ sudo vi /etc/default/grub

# 원래 내용
#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
# 수정 내용
GRUB_CMDLINE_LINUX_DEFAULT="drm.edid_firmware=HDMI-A-1:edid.bin video=HDMI-A-1:D quiet splash"

위 명령어는 /lib/firmware/ 폴더에 있는 edid.bin 파일을 이용해서 HDMI-A-1를 연결하겠다는 내용으로 이해됩니다.

내용을 저장한 후 grub을 업데이트 해 줍니다.

$ sudo update-grub

이후 다시 부팅했더니 외부 모니터가 정상 동작합니다.

 

[주의사항]

노트북에서 사용하다 보니 문제점을 확인했습니다.

강제로 EDID를 인식시키는 방법이므로, 외장 모니터가 연결되어 있지 않아도 외장 모니터가 있다고 인식합니다.

따라서 어플리케이션이 다른 화면에 나타나서 컨트롤이 어려울 수 있고, 마우스의 움직임도 이상합니다.

이때는 grub에서 예전에 사용하던 설정으로 변경하여 EDID 파일을 사용하지 않도록 했습니다.

EDID를 외장모니터에 직접 write하는 것도 방법이라고 하는데, 해당 방법은 아직 진행하지 못했습니다.

 

- End -

 

링크 1) https://wiki.debian.org/RepairEDID

링크 2) https://kodi.wiki/view/Archive:Creating_and_using_edid.bin_via_xorg.conf

링크 3) https://askubuntu.com/questions/1011098/how-to-eliminate-edid-checksum-errors

 

반응형

Websocket 스펙인 RFC6455를 살펴봤습니다.

약 3000 라인이 조금 넘는 text 파일인데, 앞서 자료들을 찾아 읽고 나서인지 기본적인 내용을 파악하기는 힘들지 않았습니다.

 

주요 내용을 정리하면 다음과 같습니다.

 

- The protocol consists of an opening handshake followed by basic message framing, layered over TCP.

- The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections
- The WebSocket Protocol is designed to supersede existing bidirectional communication technologies that use HTTP as a transport layer to benefit from existing infrastructure (proxies, filtering, authentication).

  HTTP가 제공하는 기존의 인프라를 이용할 수 있다.
- The protocol has two parts: a handshake and the data transfer.

  Handshake와 data transfer로 구성된다.
- In a handshake, the leading line from the client follows the Request-Line format. 

  And the leading line from the server follows the Status-Line format. (HTTP Spec.)
- After a successful handshake, clients and servers transfer data back and forth in conceptual units referred to in this specification as "messages". On the wire, a message is composed of one or more frames.

  Handshake 이후에 메시지들을 주고 받게 된다.
- A frame has an associated type. Each frame belonging to the same message contains the same type of data. This version of the protocol defines six frame types and leaves ten reserved for future use.

1.3. Opening Handshake

- For this header field, the server has to take the value (as present in the header field, e.g., the base64-encoded [RFC4648] version minus any leading and trailing whitespace) and concatenate this with the Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" in string form, which is unlikely to be used by network endpoints that do not understand the WebSocket Protocol. A SHA-1 hash (160 bits) [FIPS.180-3], base64-encoded (see Section 4 of [RFC4648]), of this concatenation is then returned in the server's handshake.

https://not-to-be-reset.tistory.com/91를 살펴보면, 위 내용을 Python으로 실제 시험할 수 있습니다.

- The |Sec-WebSocket-Accept| header field indicates whether the server is willing to accept the connection.

 

1.4. Closing Handshake
- By sending a Close frame and waiting for a Close frame in response, certain cases are avoided where data may be unnecessarily lost.

1.5. Design Philosophy
- The WebSocket Protocol is designed on the principle that there should be minimal framing.
- It is expected that metadata would be layered on top of WebSocket by the application layer, in the same way that metadata is layered on top of TCP by the application layer (e.g., HTTP).

4.1. Client Requirements
- The handshake consists of an HTTP Upgrade request, along with a list of required and optional header fields.

5. Data Framing
- A client MUST mask all frames that it sends to the server
- A server MUST NOT mask any frames that it sends to the client.
- Octet i of the transformed data ("transformed-octet-i") is the XOR of octet i of the original data ("original-octet-i") with octet at index i modulo 4 of the masking key ("masking-key-octet-j"):
- Control frames are identified by opcodes where the most significant bit of the opcode is 1.  Currently defined opcodes for control frames include 0x8 (Close), 0x9 (Ping), and 0xA (Pong).  Opcodes 0xB-0xF are reserved for further control frames yet to be defined.

 

이후에는 필요한 시점에 참고하면 될 것 같습니다.

 

- End -

반응형

'프로그래밍 > Network' 카테고리의 다른 글

[Network] Websocket 기초  (0) 2021.11.23

물론 스펙을 정독하고 이해하는 것이 정석이겠습니다만, 항상 쉬운 길을 찾게되네요.

하지만, 그 길을 걷다 보면 무슨 내용인지 전혀 파악이 되지 않을 때도 많습니다. ㅠㅠ

몇가지 reference link들을 정리하면서, websocket에 대해서 파악해 봅니다.

 

1. https://en.wikipedia.org/wiki/WebSocket

  • WebSocket is located at layer 7 in the OSI model and depend on TCP at layer 4. 
  • WebSocket enables streams of messages on top of TCP.

2. https://www.mischianti.org/2020/12/07/websocket-on-arduino-esp8266-and-esp32-client-1/

  • WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection.
  • The big difference from REST server is that in an http request you send request and you must wait response to have the data and start new request on the same connection, with the WS you can stream requests and stream responses than operate when you want.

그리고, 가장 중요한 그림이 나옵니다.

Rest와 Websocket 비교

3. https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers

  • A WebSocket server is nothing more than an application listening on any port of a TCP server that follows a specific protocol.
  • WebSocket servers are often separate and specialized servers (for load-balancing or other practical reasons), so you will often use a reverse proxy (such as a regular HTTP server) to detect WebSocket handshakes, pre-process them, and send those clients to a real WebSocket server. This means that you don't have to bloat your server code with cookie and authentication handlers (for example).
  • First, the server must listen for incoming socket connections using a standard TCP socket.
  • The Sec-WebSocket-Accept header is important in that the server must derive it from the Sec-WebSocket-Key that the client sent to it. To get it, concatenate the client's Sec-WebSocket-Key and the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" together (it's a "magic string"), take the SHA-1 hash of the result, and return the base64 encoding of that hash.

Frame format

내용을 정리하자면 다음과 같습니다.

  • HTTP와 유사하게 OSI 모델의 7 layer에 위치하는 application
  • Full duplex로, client의 요청 없이도 서버가 데이터의 전송을 시작할 수 있음

결론적으로 "TCP protocol 상에서 돌아가는 application으로 서버와 clients간에 full duplex를 지원하는 프로토콜" 정도로 이해할 수 있어 보입니다.

 

- End -

 

 

반응형

'프로그래밍 > Network' 카테고리의 다른 글

[Network] Websocket - RFC6455  (0) 2021.11.24

+ Recent posts