← Documents Documentation/i2c/dev-interface.rst GitHub 원문 ↗

Linux 6.18.37 · I2C

Implementing I2C device drivers in userspace

i2c-dev 장치 파일, C 예제, ioctl·libi2c API, 커널 내부 호출 경로를 설명합니다.

Source pathDocumentation/i2c/dev-interface.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

dev-interface.rst:1-221

사용자 프로그램은 동적으로 어댑터 번호를 찾고 `/dev/i2c-N`을 연 뒤 주소와 기능을 ioctl로 설정하며, i2c-dev는 요청을 검증해 표준 버스 callback으로 전달합니다.

문서 개요
항목
SourceDocumentation/i2c/dev-interface.rst
분량221 source lines
ioctl6
SMBus functions11

원문 분량과 핵심 기능을 요약합니다.

동작 흐름
어댑터 번호 탐색장치 파일 열기주소·기능 설정I2C·SMBus 전송버스 callback 실행

호출 또는 판단의 핵심 순서입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ============================================
2 Implementing I2C device drivers in userspace
3 ============================================
4
5 Usually, I2C devices are controlled by a kernel driver. But it is also
6 possible to access all devices on an adapter from userspace, through
7 the /dev interface. You need to load module i2c-dev for this.
8
9 Each registered I2C adapter gets a number, counting from 0. You can
10 examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
11 Alternatively, you can run "i2cdetect -l" to obtain a formatted list of all
12 I2C adapters present on your system at a given time. i2cdetect is part of
13 the i2c-tools package.
14
15 I2C device files are character device files with major device number 89
16 and a minor device number corresponding to the number assigned as
17 explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ...,
18 i2c-10, ...). All 256 minor device numbers are reserved for I2C.
19
20
21 C example
22 =========
23
24 So let's say you want to access an I2C adapter from a C program.
25 First, you need to include these two headers::
26
27 #include <linux/i2c-dev.h>
28 #include <i2c/smbus.h>
29
30 Now, you have to decide which adapter you want to access. You should
31 inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
32 Adapter numbers are assigned somewhat dynamically, so you can not
33 assume much about them. They can even change from one boot to the next.
34
35 Next thing, open the device file, as follows::
36
37 int file;
38 int adapter_nr = 2; /* probably dynamically determined */
39 char filename[20];
40
41 snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
42 file = open(filename, O_RDWR);
43 if (file < 0) {
44 /* ERROR HANDLING; you can check errno to see what went wrong */
45 exit(1);
46 }
47
48 When you have opened the device, you must specify with what device
49 address you want to communicate::
50
51 int addr = 0x40; /* The I2C address */
52
53 if (ioctl(file, I2C_SLAVE, addr) < 0) {
54 /* ERROR HANDLING; you can check errno to see what went wrong */
55 exit(1);
56 }
57
58 Well, you are all set up now. You can now use SMBus commands or plain
59 I2C to communicate with your device. SMBus commands are preferred if
60 the device supports them. Both are illustrated below::
61
62 __u8 reg = 0x10; /* Device register to access */
63 __s32 res;
64 char buf[10];
65
66 /* Using SMBus commands */
67 res = i2c_smbus_read_word_data(file, reg);
68 if (res < 0) {
69 /* ERROR HANDLING: I2C transaction failed */
70 } else {
71 /* res contains the read word */
72 }
73
74 /*
75 * Using I2C Write, equivalent of
76 * i2c_smbus_write_word_data(file, reg, 0x6543)
77 */
78 buf[0] = reg;
79 buf[1] = 0x43;
80 buf[2] = 0x65;
81 if (write(file, buf, 3) != 3) {
82 /* ERROR HANDLING: I2C transaction failed */
83 }
84
85 /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
86 if (read(file, buf, 1) != 1) {
87 /* ERROR HANDLING: I2C transaction failed */
88 } else {
89 /* buf[0] contains the read byte */
90 }
91
92 Note that only a subset of the I2C and SMBus protocols can be achieved by
93 the means of read() and write() calls. In particular, so-called combined
94 transactions (mixing read and write messages in the same transaction)
95 aren't supported. For this reason, this interface is almost never used by
96 user-space programs.
97
98 IMPORTANT: because of the use of inline functions, you *have* to use
99 '-O' or some variation when you compile your program!
100
101
102 Full interface description
103 ==========================
104
105 The following IOCTLs are defined:
106
107 ``ioctl(file, I2C_SLAVE, long addr)``
108 Change slave address. The address is passed in the 7 lower bits of the
109 argument (except for 10 bit addresses, passed in the 10 lower bits in this
110 case).
111
112 ``ioctl(file, I2C_TENBIT, long select)``
113 Selects ten bit addresses if select not equals 0, selects normal 7 bit
114 addresses if select equals 0. Default 0. This request is only valid
115 if the adapter has I2C_FUNC_10BIT_ADDR.
116
117 ``ioctl(file, I2C_PEC, long select)``
118 Selects SMBus PEC (packet error checking) generation and verification
119 if select not equals 0, disables if select equals 0. Default 0.
120 Used only for SMBus transactions. This request only has an effect if the
121 the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just
122 doesn't have any effect.
123
124 ``ioctl(file, I2C_FUNCS, unsigned long *funcs)``
125 Gets the adapter functionality and puts it in ``*funcs``.
126
127 ``ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)``
128 Do combined read/write transaction without stop in between.
129 Only valid if the adapter has I2C_FUNC_I2C. The argument is
130 a pointer to a::
131
132 struct i2c_rdwr_ioctl_data {
133 struct i2c_msg *msgs; /* ptr to array of simple messages */
134 int nmsgs; /* number of messages to exchange */
135 }
136
137 The msgs[] themselves contain further pointers into data buffers.
138 The function will write or read data to or from that buffers depending
139 on whether the I2C_M_RD flag is set in a particular message or not.
140 The slave address and whether to use ten bit address mode has to be
141 set in each message, overriding the values set with the above ioctl's.
142
143 ``ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)``
144 If possible, use the provided ``i2c_smbus_*`` methods described below instead
145 of issuing direct ioctls.
146
147 You can do plain I2C transactions by using read(2) and write(2) calls.
148 You do not need to pass the address byte; instead, set it through
149 ioctl I2C_SLAVE before you try to access the device.
150
151 You can do SMBus level transactions (see documentation file smbus-protocol.rst
152 for details) through the following functions::
153
154 __s32 i2c_smbus_write_quick(int file, __u8 value);
155 __s32 i2c_smbus_read_byte(int file);
156 __s32 i2c_smbus_write_byte(int file, __u8 value);
157 __s32 i2c_smbus_read_byte_data(int file, __u8 command);
158 __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
159 __s32 i2c_smbus_read_word_data(int file, __u8 command);
160 __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
161 __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
162 __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
163 __u8 *values);
164 __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
165 __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
166 __u8 *values);
167
168 All these transactions return -1 on failure; you can read errno to see
169 what happened. The 'write' transactions return 0 on success; the
170 'read' transactions return the read value, except for read_block, which
171 returns the number of values read. The block buffers need not be longer
172 than 32 bytes.
173
174 The above functions are made available by linking against the libi2c library,
175 which is provided by the i2c-tools project. See:
176 https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/.
177
178
179 Implementation details
180 ======================
181
182 For the interested, here's the code flow which happens inside the kernel
183 when you use the /dev interface to I2C:
184
185 1) Your program opens /dev/i2c-N and calls ioctl() on it, as described in
186 section "C example" above.
187
188 2) These open() and ioctl() calls are handled by the i2c-dev kernel
189 driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(),
190 respectively. You can think of i2c-dev as a generic I2C chip driver
191 that can be programmed from user-space.
192
193 3) Some ioctl() calls are for administrative tasks and are handled by
194 i2c-dev directly. Examples include I2C_SLAVE (set the address of the
195 device you want to access) and I2C_PEC (enable or disable SMBus error
196 checking on future transactions.)
197
198 4) Other ioctl() calls are converted to in-kernel function calls by
199 i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter
200 functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which
201 performs an SMBus transaction using i2c-core-smbus.c:i2c_smbus_xfer().
202
203 The i2c-dev driver is responsible for checking all the parameters that
204 come from user-space for validity. After this point, there is no
205 difference between these calls that came from user-space through i2c-dev
206 and calls that would have been performed by kernel I2C chip drivers
207 directly. This means that I2C bus drivers don't need to implement
208 anything special to support access from user-space.
209
210 5) These i2c.h functions are wrappers to the actual implementation of
211 your I2C bus driver. Each adapter must declare callback functions
212 implementing these standard calls. i2c.h:i2c_get_functionality() calls
213 i2c_adapter.algo->functionality(), while
214 i2c-core-smbus.c:i2c_smbus_xfer() calls either
215 adapter.algo->smbus_xfer() if it is implemented, or if not,
216 i2c-core-smbus.c:i2c_smbus_xfer_emulated() which in turn calls
217 i2c_adapter.algo->master_xfer().
218
219 After your I2C bus driver has processed these requests, execution runs
220 up the call chain, with almost no processing done, except by i2c-dev to
221 package the returned data, if any, in suitable format for the ioctl.
222

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

사용자 공간 /dev 인터페이스

1-20

일반적으로 I2C 장치는 커널 드라이버가 제어하지만, `i2c-dev` 모듈을 로드하면 `/dev` 인터페이스를 통해 사용자 공간에서도 어댑터의 모든 장치에 접근할 수 있습니다.

등록된 I2C 어댑터에는 0부터 번호가 붙습니다. `/sys/class/i2c-dev/`에서 번호와 어댑터의 대응을 확인하거나 i2c-tools 패키지의 `i2cdetect -l`로 현재 시스템의 모든 어댑터 목록을 형식화해 볼 수 있습니다.

I2C 장치 파일은 주 장치 번호 89를 사용하는 문자 장치이며 부 장치 번호는 어댑터 번호와 같습니다. 이름은 `i2c-%d`, 즉 `i2c-0`, `i2c-1`, `i2c-10` 형식이어야 합니다. 256개 부 장치 번호 전체가 I2C용으로 예약되어 있습니다.

I2C 사용자 공간 장치
항목
필수 모듈`i2c-dev`
어댑터 확인`/sys/class/i2c-dev/` 또는 `i2cdetect -l`
장치 유형문자 장치
주 장치 번호89
부 장치 번호어댑터 번호, 0~255 예약
장치 파일`/dev/i2c-%d`

어댑터 번호와 장치 파일 규칙을 정리합니다.

사용자 공간 I2C 접근
I2C 버스 드라이버가 어댑터 등록`i2c-dev`가 번호 할당`/dev/i2c-N` 문자 장치 생성사용자 프로그램이 장치 열기`ioctl`·SMBus 함수로 전송

커널 어댑터가 i2c-dev 문자 장치로 노출되는 경로입니다.

============================================
Implementing I2C device drivers in userspace
============================================

Usually, I2C devices are controlled by a kernel driver. But it is also
possible to access all devices on an adapter from userspace, through
the /dev interface. You need to load module i2c-dev for this.

Each registered I2C adapter gets a number, counting from 0. You can
examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
Alternatively, you can run "i2cdetect -l" to obtain a formatted list of all
I2C adapters present on your system at a given time. i2cdetect is part of
the i2c-tools package.

I2C device files are character device files with major device number 89
and a minor device number corresponding to the number assigned as
explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ...,
i2c-10, ...). All 256 minor device numbers are reserved for I2C.

C 프로그램의 어댑터 열기와 주소 설정

21-57

C 프로그램에서 I2C 어댑터에 접근하려면 `<linux/i2c-dev.h>`와 `<i2c/smbus.h>` 헤더를 포함합니다.

사용할 어댑터는 `/sys/class/i2c-dev/` 또는 `i2cdetect -l`로 결정해야 합니다. 번호는 동적으로 할당되며 부팅할 때마다 바뀔 수도 있으므로 고정값이라고 가정해서는 안 됩니다.

예제는 `adapter_nr = 2`를 사용해 `snprintf(filename, 19, "/dev/i2c-%d", adapter_nr)`로 파일명을 만들고 `open(filename, O_RDWR)`로 엽니다. 실패하면 `errno`를 확인해 원인을 처리하고 종료합니다.

장치 파일을 연 다음 통신할 I2C 주소를 지정해야 합니다. 예제 주소는 `0x40`이며 `ioctl(file, I2C_SLAVE, addr)`로 설정합니다. 이 호출이 실패해도 `errno`를 확인해 처리합니다.

C 초기화 순서
단계코드·의미
헤더`<linux/i2c-dev.h>`, `<i2c/smbus.h>`
번호 탐색`/sys/class/i2c-dev/` 또는 `i2cdetect -l`
파일명`/dev/i2c-%d`
열기`open(filename, O_RDWR)`
슬레이브 주소`addr = 0x40`
주소 적용`ioctl(file, I2C_SLAVE, addr)`
오류`errno` 확인

예제의 헤더, 파일, 주소 설정을 구조화했습니다.

C 프로그램 준비
필수 헤더 포함현재 어댑터 번호 탐색`/dev/i2c-N` 열기`I2C_SLAVE`로 주소 설정전송 함수 호출 준비

동적 어댑터 번호를 찾은 뒤 파일과 슬레이브 주소를 차례로 설정합니다.

C example
=========

So let's say you want to access an I2C adapter from a C program.
First, you need to include these two headers::

  #include <linux/i2c-dev.h>
  #include <i2c/smbus.h>

Now, you have to decide which adapter you want to access. You should
inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
Adapter numbers are assigned somewhat dynamically, so you can not
assume much about them. They can even change from one boot to the next.

Next thing, open the device file, as follows::

  int file;
  int adapter_nr = 2; /* probably dynamically determined */
  char filename[20];

  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
  file = open(filename, O_RDWR);
  if (file < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

When you have opened the device, you must specify with what device
address you want to communicate::

  int addr = 0x40; /* The I2C address */

  if (ioctl(file, I2C_SLAVE, addr) < 0) {
    /* ERROR HANDLING; you can check errno to see what went wrong */
    exit(1);
  }

SMBus와 일반 I2C 전송 예제

58-101

설정을 마치면 SMBus 명령 또는 일반 I2C로 장치와 통신할 수 있습니다. 장치가 SMBus를 지원한다면 SMBus 명령을 우선 사용하는 것이 좋습니다.

예제는 레지스터 `0x10`을 `i2c_smbus_read_word_data(file, reg)`로 읽습니다. 음수면 트랜잭션 실패이고, 성공하면 반환값 `res`에 읽은 워드가 들어 있습니다.

일반 I2C 쓰기 예제는 `i2c_smbus_write_word_data(file, reg, 0x6543)`와 같은 효과를 내기 위해 버퍼에 `reg`, `0x43`, `0x65`를 순서대로 넣고 `write(file, buf, 3)`가 3을 반환하는지 확인합니다.

일반 I2C 읽기 예제는 `i2c_smbus_read_byte(file)`와 같은 효과를 위해 `read(file, buf, 1)`을 호출하며, 성공하면 `buf[0]`에 읽은 바이트가 있습니다.

`read()`와 `write()`로 구현할 수 있는 I2C·SMBus 프로토콜은 일부뿐입니다. 특히 한 트랜잭션에서 읽기와 쓰기 메시지를 섞는 combined transaction을 지원하지 않으므로 사용자 공간 프로그램은 이 인터페이스를 거의 사용하지 않습니다.

SMBus 함수가 inline 함수이므로 프로그램을 컴파일할 때 반드시 `-O` 또는 다른 최적화 옵션을 사용해야 합니다.

C 전송 예제
작업호출성공 조건
워드 읽기`i2c_smbus_read_word_data(file, reg)``res >= 0`
워드 쓰기 상당`write(file, buf, 3)`반환값 3
바이트 읽기 상당`read(file, buf, 1)`반환값 1
combined transaction`read`/`write` 단독 인터페이스지원하지 않음
컴파일`-O` 또는 변형inline 함수 때문에 필수

SMBus helper와 일반 read/write의 대응 관계입니다.

사용자 공간 전송 선택
장치의 SMBus 지원 확인지원하면 `i2c_smbus_*` 우선단순 I2C는 `read`·`write` 가능combined transaction은 `I2C_RDWR` 사용반환값과 `errno` 검사

장치 기능에 맞춰 SMBus helper 또는 I2C_RDWR를 선택합니다.

Well, you are all set up now. You can now use SMBus commands or plain
I2C to communicate with your device. SMBus commands are preferred if
the device supports them. Both are illustrated below::

  __u8 reg = 0x10; /* Device register to access */
  __s32 res;
  char buf[10];

  /* Using SMBus commands */
  res = i2c_smbus_read_word_data(file, reg);
  if (res < 0) {
    /* ERROR HANDLING: I2C transaction failed */
  } else {
    /* res contains the read word */
  }

  /*
   * Using I2C Write, equivalent of
   * i2c_smbus_write_word_data(file, reg, 0x6543)
   */
  buf[0] = reg;
  buf[1] = 0x43;
  buf[2] = 0x65;
  if (write(file, buf, 3) != 3) {
    /* ERROR HANDLING: I2C transaction failed */
  }

  /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
  if (read(file, buf, 1) != 1) {
    /* ERROR HANDLING: I2C transaction failed */
  } else {
    /* buf[0] contains the read byte */
  }

Note that only a subset of the I2C and SMBus protocols can be achieved by
the means of read() and write() calls. In particular, so-called combined
transactions (mixing read and write messages in the same transaction)
aren't supported. For this reason, this interface is almost never used by
user-space programs.

IMPORTANT: because of the use of inline functions, you *have* to use
'-O' or some variation when you compile your program!

전체 ioctl 인터페이스

102-146

`ioctl(file, I2C_SLAVE, long addr)`는 슬레이브 주소를 바꿉니다. 일반 주소는 인자의 하위 7비트, 10비트 주소는 하위 10비트로 전달합니다.

`ioctl(file, I2C_TENBIT, long select)`는 `select != 0`이면 10비트, 0이면 일반 7비트 주소를 선택합니다. 기본값은 0이며 어댑터가 `I2C_FUNC_10BIT_ADDR`를 제공할 때만 유효합니다.

`ioctl(file, I2C_PEC, long select)`는 `select != 0`이면 SMBus PEC 생성·검증을 켜고 0이면 끕니다. 기본값은 0이고 SMBus 트랜잭션에만 사용합니다. `I2C_FUNC_SMBUS_PEC`가 있을 때만 효과가 있지만, 없어도 호출은 안전하며 아무 효과가 없습니다.

`ioctl(file, I2C_FUNCS, unsigned long *funcs)`는 어댑터 기능을 얻어 `*funcs`에 저장합니다.

`ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)`는 중간 STOP 없이 combined read/write 트랜잭션을 수행하며 `I2C_FUNC_I2C`가 있어야 합니다. 인자는 `struct i2c_msg *msgs`와 메시지 수 `int nmsgs`를 가진 구조체를 가리킵니다.

각 `msgs[]`는 데이터 버퍼를 가리키는 추가 포인터를 포함합니다. 메시지의 `I2C_M_RD` 플래그 유무에 따라 버퍼를 읽거나 씁니다. 슬레이브 주소와 10비트 주소 사용 여부는 메시지마다 설정해야 하며 앞선 ioctl 값보다 우선합니다.

`ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)`를 직접 호출하기보다 가능하면 아래의 `i2c_smbus_*` 메서드를 사용하십시오.

i2c-dev ioctl
ioctl기능필요 능력
`I2C_SLAVE`7비트 또는 10비트 슬레이브 주소 설정주소 형식에 따름
`I2C_TENBIT`10비트 주소 모드 선택`I2C_FUNC_10BIT_ADDR`
`I2C_PEC`SMBus PEC 생성·검증`I2C_FUNC_SMBUS_PEC`
`I2C_FUNCS`기능 마스크를 `*funcs`에 저장없음
`I2C_RDWR`STOP 없는 combined read/write`I2C_FUNC_I2C`
`I2C_SMBUS`직접 SMBus 요청helper 사용 권장

주소 모드, 기능 조회, 복합 전송과 SMBus 요청을 정리합니다.

I2C_RDWR 메시지 처리
`i2c_rdwr_ioctl_data` 준비`msgs` 배열과 `nmsgs` 지정각 메시지에 주소·10비트 모드 설정`I2C_M_RD`로 읽기·쓰기 구분중간 STOP 없이 전체 메시지 실행

메시지마다 주소·방향·버퍼를 독립적으로 지정합니다.

Full interface description
==========================

The following IOCTLs are defined:

``ioctl(file, I2C_SLAVE, long addr)``
  Change slave address. The address is passed in the 7 lower bits of the
  argument (except for 10 bit addresses, passed in the 10 lower bits in this
  case).

``ioctl(file, I2C_TENBIT, long select)``
  Selects ten bit addresses if select not equals 0, selects normal 7 bit
  addresses if select equals 0. Default 0.  This request is only valid
  if the adapter has I2C_FUNC_10BIT_ADDR.

``ioctl(file, I2C_PEC, long select)``
  Selects SMBus PEC (packet error checking) generation and verification
  if select not equals 0, disables if select equals 0. Default 0.
  Used only for SMBus transactions.  This request only has an effect if the
  the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just
  doesn't have any effect.

``ioctl(file, I2C_FUNCS, unsigned long *funcs)``
  Gets the adapter functionality and puts it in ``*funcs``.

``ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)``
  Do combined read/write transaction without stop in between.
  Only valid if the adapter has I2C_FUNC_I2C.  The argument is
  a pointer to a::

    struct i2c_rdwr_ioctl_data {
      struct i2c_msg *msgs;  /* ptr to array of simple messages */
      int nmsgs;             /* number of messages to exchange */
    }

  The msgs[] themselves contain further pointers into data buffers.
  The function will write or read data to or from that buffers depending
  on whether the I2C_M_RD flag is set in a particular message or not.
  The slave address and whether to use ten bit address mode has to be
  set in each message, overriding the values set with the above ioctl's.

``ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)``
  If possible, use the provided ``i2c_smbus_*`` methods described below instead
  of issuing direct ioctls.

일반 I2C와 libi2c SMBus 함수

147-178

일반 I2C 트랜잭션은 `read(2)`와 `write(2)`로 수행할 수 있습니다. 주소 바이트를 데이터에 넣지 말고 장치 접근 전에 `I2C_SLAVE` ioctl로 주소를 설정합니다.

SMBus 수준 트랜잭션의 자세한 프로토콜은 `smbus-protocol.rst`를 참조하십시오. 사용자 공간에서는 Quick, Byte, Byte Data, Word Data, Process Call, Block Process Call, Block Data 읽기·쓰기 함수를 사용할 수 있습니다.

모든 함수는 실패 시 -1을 반환하며 `errno`로 원인을 확인합니다. 쓰기 함수는 성공 시 0, 읽기 함수는 읽은 값을 반환합니다. 단 `read_block`은 읽은 값의 개수를 반환합니다. 블록 버퍼는 32바이트보다 길 필요가 없습니다.

이 함수들은 i2c-tools 프로젝트가 제공하는 `libi2c` 라이브러리에 링크하면 사용할 수 있습니다. 저장소는 `https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/`입니다.

libi2c SMBus 함수
함수동작
`i2c_smbus_write_quick(file, value)`Quick command 쓰기
`i2c_smbus_read_byte(file)`바이트 읽기
`i2c_smbus_write_byte(file, value)`바이트 쓰기
`i2c_smbus_read_byte_data(file, command)`명령 기반 바이트 데이터 읽기
`i2c_smbus_write_byte_data(file, command, value)`명령 기반 바이트 데이터 쓰기
`i2c_smbus_read_word_data(file, command)`명령 기반 워드 데이터 읽기
`i2c_smbus_write_word_data(file, command, value)`명령 기반 워드 데이터 쓰기
`i2c_smbus_process_call(file, command, value)`Process Call
`i2c_smbus_block_process_call(file, command, length, values)`Block Process Call
`i2c_smbus_read_block_data(file, command, values)`블록 데이터 읽기
`i2c_smbus_write_block_data(file, command, length, values)`블록 데이터 쓰기

원문에 선언된 사용자 공간 함수 11개를 모두 보존합니다.

libi2c 호출 결과
`libi2c`에 링크적절한 `i2c_smbus_*` 함수 호출실패 -1이면 `errno` 확인쓰기 성공은 0읽기는 값, block read는 개수 반환

전송 유형별 반환값을 해석합니다.

You can do plain I2C transactions by using read(2) and write(2) calls.
You do not need to pass the address byte; instead, set it through
ioctl I2C_SLAVE before you try to access the device.

You can do SMBus level transactions (see documentation file smbus-protocol.rst
for details) through the following functions::

  __s32 i2c_smbus_write_quick(int file, __u8 value);
  __s32 i2c_smbus_read_byte(int file);
  __s32 i2c_smbus_write_byte(int file, __u8 value);
  __s32 i2c_smbus_read_byte_data(int file, __u8 command);
  __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
  __s32 i2c_smbus_read_word_data(int file, __u8 command);
  __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
  __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
                                     __u8 *values);
  __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
  __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
                                   __u8 *values);

All these transactions return -1 on failure; you can read errno to see
what happened. The 'write' transactions return 0 on success; the
'read' transactions return the read value, except for read_block, which
returns the number of values read. The block buffers need not be longer
than 32 bytes.

The above functions are made available by linking against the libi2c library,
which is provided by the i2c-tools project.  See:
https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/.

커널 내부 호출 흐름

179-221

사용자 프로그램은 `/dev/i2c-N`을 열고 앞의 C 예제처럼 `ioctl()`을 호출합니다.

`open()`과 `ioctl()`은 각각 `i2c-dev.c:i2cdev_open()`과 `i2c-dev.c:i2cdev_ioctl()`이 처리합니다. `i2c-dev`는 사용자 공간에서 프로그래밍할 수 있는 범용 I2C 칩 드라이버로 생각할 수 있습니다.

일부 ioctl은 관리 작업이므로 i2c-dev가 직접 처리합니다. 예를 들어 `I2C_SLAVE`는 접근할 장치 주소를 설정하고 `I2C_PEC`는 이후 SMBus 트랜잭션의 오류 검사를 켜거나 끕니다.

다른 ioctl은 i2c-dev가 커널 내부 함수 호출로 변환합니다. `I2C_FUNCS`는 `i2c.h:i2c_get_functionality()`로 어댑터 기능을 조회하고, `I2C_SMBUS`는 `i2c-core-smbus.c:i2c_smbus_xfer()`로 SMBus 트랜잭션을 수행합니다.

i2c-dev는 사용자 공간에서 온 모든 매개변수의 유효성을 검사합니다. 그 뒤에는 i2c-dev를 거친 호출과 커널 I2C 칩 드라이버가 직접 수행한 호출 사이에 차이가 없습니다. 따라서 I2C 버스 드라이버는 사용자 공간 접근을 위해 별도 기능을 구현할 필요가 없습니다.

이 `i2c.h` 함수들은 실제 버스 드라이버 구현의 wrapper입니다. 각 어댑터는 표준 호출의 callback을 선언해야 합니다. `i2c_get_functionality()`는 `i2c_adapter.algo->functionality()`를 호출합니다.

`i2c_smbus_xfer()`는 구현되어 있으면 `adapter.algo->smbus_xfer()`를 호출합니다. 없으면 `i2c_smbus_xfer_emulated()`가 `i2c_adapter.algo->master_xfer()`를 호출해 에뮬레이션합니다.

버스 드라이버가 요청을 처리한 뒤 실행은 호출 사슬을 거슬러 올라갑니다. 반환 데이터가 있으면 i2c-dev가 ioctl에 맞는 형식으로 포장하는 것 외에는 거의 처리하지 않습니다.

i2c-dev 커널 호출 경로
단계함수·동작
장치 열기`i2cdev_open()`
ioctl 진입`i2cdev_ioctl()`
관리 요청`I2C_SLAVE`, `I2C_PEC`를 i2c-dev가 처리
기능 조회`i2c_get_functionality()` → `algo->functionality()`
SMBus 직접`i2c_smbus_xfer()` → `algo->smbus_xfer()`
SMBus 에뮬레이션`i2c_smbus_xfer_emulated()` → `algo->master_xfer()`
복귀i2c-dev가 반환 데이터를 ioctl 형식으로 포장

사용자 호출과 커널 callback의 대응을 정리합니다.

사용자 공간에서 버스 callback까지
프로그램이 `/dev/i2c-N` 열기`i2cdev_ioctl()`이 요청과 매개변수 검증I2C core 표준 함수 호출어댑터 `functionality`·`smbus_xfer`·`master_xfer` callback결과를 i2c-dev가 사용자 형식으로 반환

i2c-dev가 매개변수를 검증한 뒤 표준 커널 호출로 변환합니다.

Implementation details
======================

For the interested, here's the code flow which happens inside the kernel
when you use the /dev interface to I2C:

1) Your program opens /dev/i2c-N and calls ioctl() on it, as described in
   section "C example" above.

2) These open() and ioctl() calls are handled by the i2c-dev kernel
   driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(),
   respectively. You can think of i2c-dev as a generic I2C chip driver
   that can be programmed from user-space.

3) Some ioctl() calls are for administrative tasks and are handled by
   i2c-dev directly. Examples include I2C_SLAVE (set the address of the
   device you want to access) and I2C_PEC (enable or disable SMBus error
   checking on future transactions.)

4) Other ioctl() calls are converted to in-kernel function calls by
   i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter
   functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which
   performs an SMBus transaction using i2c-core-smbus.c:i2c_smbus_xfer().

   The i2c-dev driver is responsible for checking all the parameters that
   come from user-space for validity. After this point, there is no
   difference between these calls that came from user-space through i2c-dev
   and calls that would have been performed by kernel I2C chip drivers
   directly. This means that I2C bus drivers don't need to implement
   anything special to support access from user-space.

5) These i2c.h functions are wrappers to the actual implementation of
   your I2C bus driver. Each adapter must declare callback functions
   implementing these standard calls. i2c.h:i2c_get_functionality() calls
   i2c_adapter.algo->functionality(), while
   i2c-core-smbus.c:i2c_smbus_xfer() calls either
   adapter.algo->smbus_xfer() if it is implemented, or if not,
   i2c-core-smbus.c:i2c_smbus_xfer_emulated() which in turn calls
   i2c_adapter.algo->master_xfer().

After your I2C bus driver has processed these requests, execution runs
up the call chain, with almost no processing done, except by i2c-dev to
package the returned data, if any, in suitable format for the ioctl.