Documentation/driver-api/usb/writing_usb_driver.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

Writing USB Device Drivers

usb-skeleton 예제로 usb_driver 등록, device ID matching, probe·disconnect, bulk URB I/O와 surprise removal 수명주기를 설명하는 한국어 전문 번역입니다.

Source pathDocumentation/driver-api/usb/writing_usb_driver.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약·해설

writing_usb_driver.rst:1-328

USB skeleton driver는 ID table과 usb_driver callback으로 interface에 bind되고, endpoint·buffer·URB를 준비해 userspace file operation을 제공합니다. 물리 unplug가 open handle과 동시에 발생할 수 있으므로 pending I/O 중단, presence 확인, reference 기반 최종 free가 핵심입니다.

문서 구성
원문 줄핵심 내용
1-47USB 지원 역사·skeleton
48-135Driver 등록·ID table
136-179Probe·disconnect·open
180-222Bulk write URB
223-252동기 bulk read
253-292Release·surprise removal
293-328Interrupt·ISO·자료

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. _writing-usb-driver:
2
3 ==========================
4 Writing USB Device Drivers
5 ==========================
6
7 :Author: Greg Kroah-Hartman
8
9 Introduction
10 ============
11
12 The Linux USB subsystem has grown from supporting only two different
13 types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
14 different types of devices in the 2.4 kernel. Linux currently supports
15 almost all USB class devices (standard types of devices like keyboards,
16 mice, modems, printers and speakers) and an ever-growing number of
17 vendor-specific devices (such as USB to serial converters, digital
18 cameras, Ethernet devices and MP3 players). For a full list of the
19 different USB devices currently supported, see Resources.
20
21 The remaining kinds of USB devices that do not have support on Linux are
22 almost all vendor-specific devices. Each vendor decides to implement a
23 custom protocol to talk to their device, so a custom driver usually
24 needs to be created. Some vendors are open with their USB protocols and
25 help with the creation of Linux drivers, while others do not publish
26 them, and developers are forced to reverse-engineer. See Resources for
27 some links to handy reverse-engineering tools.
28
29 Because each different protocol causes a new driver to be created, I
30 have written a generic USB driver skeleton, modelled after the
31 pci-skeleton.c file in the kernel source tree upon which many PCI
32 network drivers have been based. This USB skeleton can be found at
33 drivers/usb/usb-skeleton.c in the kernel source tree. In this article I
34 will walk through the basics of the skeleton driver, explaining the
35 different pieces and what needs to be done to customize it to your
36 specific device.
37
38 Linux USB Basics
39 ================
40
41 If you are going to write a Linux USB driver, please become familiar
42 with the USB protocol specification. It can be found, along with many
43 other useful documents, at the USB home page (see Resources). An
44 excellent introduction to the Linux USB subsystem can be found at the
45 USB Working Devices List (see Resources). It explains how the Linux USB
46 subsystem is structured and introduces the reader to the concept of USB
47 urbs (USB Request Blocks), which are essential to USB drivers.
48
49 The first thing a Linux USB driver needs to do is register itself with
50 the Linux USB subsystem, giving it some information about which devices
51 the driver supports and which functions to call when a device supported
52 by the driver is inserted or removed from the system. All of this
53 information is passed to the USB subsystem in the :c:type:`usb_driver`
54 structure. The skeleton driver declares a :c:type:`usb_driver` as::
55
56 static struct usb_driver skel_driver = {
57 .name = "skeleton",
58 .probe = skel_probe,
59 .disconnect = skel_disconnect,
60 .suspend = skel_suspend,
61 .resume = skel_resume,
62 .pre_reset = skel_pre_reset,
63 .post_reset = skel_post_reset,
64 .id_table = skel_table,
65 .supports_autosuspend = 1,
66 };
67
68
69 The variable name is a string that describes the driver. It is used in
70 informational messages printed to the system log. The probe and
71 disconnect function pointers are called when a device that matches the
72 information provided in the ``id_table`` variable is either seen or
73 removed.
74
75 The fops and minor variables are optional. Most USB drivers hook into
76 another kernel subsystem, such as the SCSI, network or TTY subsystem.
77 These types of drivers register themselves with the other kernel
78 subsystem, and any user-space interactions are provided through that
79 interface. But for drivers that do not have a matching kernel subsystem,
80 such as MP3 players or scanners, a method of interacting with user space
81 is needed. The USB subsystem provides a way to register a minor device
82 number and a set of :c:type:`file_operations` function pointers that enable
83 this user-space interaction. The skeleton driver needs this kind of
84 interface, so it provides a minor starting number and a pointer to its
85 :c:type:`file_operations` functions.
86
87 The USB driver is then registered with a call to usb_register(),
88 usually in the driver's init function, as shown here::
89
90 static int __init usb_skel_init(void)
91 {
92 int result;
93
94 /* register this driver with the USB subsystem */
95 result = usb_register(&skel_driver);
96 if (result < 0) {
97 pr_err("usb_register failed for the %s driver. Error number %d\n",
98 skel_driver.name, result);
99 return -1;
100 }
101
102 return 0;
103 }
104 module_init(usb_skel_init);
105
106
107 When the driver is unloaded from the system, it needs to deregister
108 itself with the USB subsystem. This is done with usb_deregister()
109 function::
110
111 static void __exit usb_skel_exit(void)
112 {
113 /* deregister this driver with the USB subsystem */
114 usb_deregister(&skel_driver);
115 }
116 module_exit(usb_skel_exit);
117
118
119 To enable the linux-hotplug system to load the driver automatically when
120 the device is plugged in, you need to create a ``MODULE_DEVICE_TABLE``.
121 The following code tells the hotplug scripts that this module supports a
122 single device with a specific vendor and product ID::
123
124 /* table of devices that work with this driver */
125 static struct usb_device_id skel_table [] = {
126 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
127 { } /* Terminating entry */
128 };
129 MODULE_DEVICE_TABLE (usb, skel_table);
130
131
132 There are other macros that can be used in describing a struct
133 :c:type:`usb_device_id` for drivers that support a whole class of USB
134 drivers. See :ref:`usb.h <usb_header>` for more information on this.
135
136 Device operation
137 ================
138
139 When a device is plugged into the USB bus that matches the device ID
140 pattern that your driver registered with the USB core, the probe
141 function is called. The :c:type:`usb_device` structure, interface number and
142 the interface ID are passed to the function::
143
144 static int skel_probe(struct usb_interface *interface,
145 const struct usb_device_id *id)
146
147
148 The driver now needs to verify that this device is actually one that it
149 can accept. If so, it returns 0. If not, or if any error occurs during
150 initialization, an errorcode (such as ``-ENOMEM`` or ``-ENODEV``) is
151 returned from the probe function.
152
153 In the skeleton driver, we determine what end points are marked as
154 bulk-in and bulk-out. We create buffers to hold the data that will be
155 sent and received from the device, and a USB urb to write data to the
156 device is initialized.
157
158 Conversely, when the device is removed from the USB bus, the disconnect
159 function is called with the device pointer. The driver needs to clean
160 any private data that has been allocated at this time and to shut down
161 any pending urbs that are in the USB system.
162
163 Now that the device is plugged into the system and the driver is bound
164 to the device, any of the functions in the :c:type:`file_operations` structure
165 that were passed to the USB subsystem will be called from a user program
166 trying to talk to the device. The first function called will be open, as
167 the program tries to open the device for I/O. We increment our private
168 usage count and save a pointer to our internal structure in the file
169 structure. This is done so that future calls to file operations will
170 enable the driver to determine which device the user is addressing. All
171 of this is done with the following code::
172
173 /* increment our usage count for the device */
174 kref_get(&dev->kref);
175
176 /* save our object in the file's private structure */
177 file->private_data = dev;
178
179
180 After the open function is called, the read and write functions are
181 called to receive and send data to the device. In the ``skel_write``
182 function, we receive a pointer to some data that the user wants to send
183 to the device and the size of the data. The function determines how much
184 data it can send to the device based on the size of the write urb it has
185 created (this size depends on the size of the bulk out end point that
186 the device has). Then it copies the data from user space to kernel
187 space, points the urb to the data and submits the urb to the USB
188 subsystem. This can be seen in the following code::
189
190 /* we can only write as much as 1 urb will hold */
191 size_t writesize = min_t(size_t, count, MAX_TRANSFER);
192
193 /* copy the data from user space into our urb */
194 copy_from_user(buf, user_buffer, writesize);
195
196 /* set up our urb */
197 usb_fill_bulk_urb(urb,
198 dev->udev,
199 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
200 buf,
201 writesize,
202 skel_write_bulk_callback,
203 dev);
204
205 /* send the data out the bulk port */
206 retval = usb_submit_urb(urb, GFP_KERNEL);
207 if (retval) {
208 dev_err(&dev->interface->dev,
209 "%s - failed submitting write urb, error %d\n",
210 __func__, retval);
211 }
212
213
214 When the write urb is filled up with the proper information using the
215 :c:func:`usb_fill_bulk_urb` function, we point the urb's completion callback
216 to call our own ``skel_write_bulk_callback`` function. This function is
217 called when the urb is finished by the USB subsystem. The callback
218 function is called in interrupt context, so caution must be taken not to
219 do very much processing at that time. Our implementation of
220 ``skel_write_bulk_callback`` merely reports if the urb was completed
221 successfully or not and then returns.
222
223 The read function works a bit differently from the write function in
224 that we do not use an urb to transfer data from the device to the
225 driver. Instead we call the :c:func:`usb_bulk_msg` function, which can be used
226 to send or receive data from a device without having to create urbs and
227 handle urb completion callback functions. We call the :c:func:`usb_bulk_msg`
228 function, giving it a buffer into which to place any data received from
229 the device and a timeout value. If the timeout period expires without
230 receiving any data from the device, the function will fail and return an
231 error message. This can be shown with the following code::
232
233 /* do an immediate bulk read to get data from the device */
234 retval = usb_bulk_msg (skel->dev,
235 usb_rcvbulkpipe (skel->dev,
236 skel->bulk_in_endpointAddr),
237 skel->bulk_in_buffer,
238 skel->bulk_in_size,
239 &count, 5000);
240 /* if the read was successful, copy the data to user space */
241 if (!retval) {
242 if (copy_to_user (buffer, skel->bulk_in_buffer, count))
243 retval = -EFAULT;
244 else
245 retval = count;
246 }
247
248
249 The :c:func:`usb_bulk_msg` function can be very useful for doing single reads
250 or writes to a device; however, if you need to read or write constantly to
251 a device, it is recommended to set up your own urbs and submit them to
252 the USB subsystem.
253
254 When the user program releases the file handle that it has been using to
255 talk to the device, the release function in the driver is called. In
256 this function we decrement our private usage count and wait for possible
257 pending writes::
258
259 /* decrement our usage count for the device */
260 --skel->open_count;
261
262
263 One of the more difficult problems that USB drivers must be able to
264 handle smoothly is the fact that the USB device may be removed from the
265 system at any point in time, even if a program is currently talking to
266 it. It needs to be able to shut down any current reads and writes and
267 notify the user-space programs that the device is no longer there. The
268 following code (function ``skel_delete``) is an example of how to do
269 this::
270
271 static inline void skel_delete (struct usb_skel *dev)
272 {
273 kfree (dev->bulk_in_buffer);
274 if (dev->bulk_out_buffer != NULL)
275 usb_free_coherent (dev->udev, dev->bulk_out_size,
276 dev->bulk_out_buffer,
277 dev->write_urb->transfer_dma);
278 usb_free_urb (dev->write_urb);
279 kfree (dev);
280 }
281
282
283 If a program currently has an open handle to the device, we reset the
284 flag ``device_present``. For every read, write, release and other
285 functions that expect a device to be present, the driver first checks
286 this flag to see if the device is still present. If not, it releases
287 that the device has disappeared, and a ``-ENODEV`` error is returned to the
288 user-space program. When the release function is eventually called, it
289 determines if there is no device and if not, it does the cleanup that
290 the ``skel_disconnect`` function normally does if there are no open files
291 on the device (see Listing 5).
292
293 Isochronous Data
294 ================
295
296 This usb-skeleton driver does not have any examples of interrupt or
297 isochronous data being sent to or from the device. Interrupt data is
298 sent almost exactly as bulk data is, with a few minor exceptions.
299 Isochronous data works differently with continuous streams of data being
300 sent to or from the device. The audio and video camera drivers are very
301 good examples of drivers that handle isochronous data and will be useful
302 if you also need to do this.
303
304 Conclusion
305 ==========
306
307 Writing Linux USB device drivers is not a difficult task as the
308 usb-skeleton driver shows. This driver, combined with the other current
309 USB drivers, should provide enough examples to help a beginning author
310 create a working driver in a minimal amount of time. The linux-usb-devel
311 mailing list archives also contain a lot of helpful information.
312
313 Resources
314 =========
315
316 The Linux USB Project:
317 http://www.linux-usb.org/
318
319 Linux Hotplug Project:
320 http://linux-hotplug.sourceforge.net/
321
322 linux-usb Mailing List Archives:
323 https://lore.kernel.org/linux-usb/
324
325 Programming Guide for Linux USB Device Drivers:
326 https://lmu.web.psi.ch/docu/manuals/software_manuals/linux_sl/usb_linux_programming_guide.pdf
327
328 USB Home Page: https://www.usb.org
329

3. 한국어 전문 번역

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

Linux USB driver 역사와 skeleton의 목적

1-47

Linux USB subsystem은 2.2.7 kernel에서 mouse와 keyboard 두 종류만 지원하던 단계에서 2.4 kernel의 20종 이상으로 성장했습니다. 현재는 keyboard, mouse, modem, printer, speaker 같은 거의 모든 USB class device와 USB-to-serial converter, digital camera, Ethernet device, MP3 player 같은 vendor-specific device를 폭넓게 지원합니다.

남은 미지원 장치는 대부분 vendor-specific protocol을 사용합니다. Vendor가 protocol을 공개하고 Linux driver 개발을 돕기도 하지만, 공개하지 않으면 developer가 reverse engineering으로 custom driver를 작성해야 합니다.

Protocol마다 새 driver가 필요하므로 Greg Kroah-Hartman은 PCI `pci-skeleton.c`와 유사한 generic USB skeleton을 만들었습니다. 예제는 `drivers/usb/usb-skeleton.c`에 있으며 특정 device에 맞춰 바꿔야 할 driver 구성 요소를 보여 줍니다.

USB driver를 작성하려면 USB protocol specification, Linux USB subsystem 구조와 USB Request Block(URB)을 먼저 이해해야 합니다. USB Working Devices List와 원문 Resources가 배경 자료를 제공합니다.

USB driver 작성 출발점
주제핵심
USB class device표준 class protocol로 공통 driver 활용
Vendor-specific deviceCustom protocol과 전용 driver 필요
Reverse engineering비공개 protocol 분석 도구 활용
Skeleton source`drivers/usb/usb-skeleton.c`
핵심 추상화USB Request Block(URB)
기본 자료USB specification·Linux USB 구조

.. _writing-usb-driver:

==========================
Writing USB Device Drivers
==========================

:Author: Greg Kroah-Hartman

Introduction
============

The Linux USB subsystem has grown from supporting only two different
types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
different types of devices in the 2.4 kernel. Linux currently supports
almost all USB class devices (standard types of devices like keyboards,
mice, modems, printers and speakers) and an ever-growing number of
vendor-specific devices (such as USB to serial converters, digital
cameras, Ethernet devices and MP3 players). For a full list of the
different USB devices currently supported, see Resources.

The remaining kinds of USB devices that do not have support on Linux are
almost all vendor-specific devices. Each vendor decides to implement a
custom protocol to talk to their device, so a custom driver usually
needs to be created. Some vendors are open with their USB protocols and
help with the creation of Linux drivers, while others do not publish
them, and developers are forced to reverse-engineer. See Resources for
some links to handy reverse-engineering tools.

Because each different protocol causes a new driver to be created, I
have written a generic USB driver skeleton, modelled after the
pci-skeleton.c file in the kernel source tree upon which many PCI
network drivers have been based. This USB skeleton can be found at
drivers/usb/usb-skeleton.c in the kernel source tree. In this article I
will walk through the basics of the skeleton driver, explaining the
different pieces and what needs to be done to customize it to your
specific device.

Linux USB Basics
================

If you are going to write a Linux USB driver, please become familiar
with the USB protocol specification. It can be found, along with many
other useful documents, at the USB home page (see Resources). An
excellent introduction to the Linux USB subsystem can be found at the
USB Working Devices List (see Resources). It explains how the Linux USB
subsystem is structured and introduces the reader to the concept of USB
urbs (USB Request Blocks), which are essential to USB drivers.

usb_driver 등록, minor interface와 device ID table

48-135

USB driver는 지원 device 정보와 삽입·제거 때 호출할 함수를 `struct usb_driver`로 USB subsystem에 등록합니다. Skeleton은 이름, `probe`, `disconnect`, suspend·resume, reset 전후 callback, `id_table`, autosuspend 지원을 선언합니다.

Driver 이름은 system log에 사용되고 `id_table`과 맞는 device가 나타나거나 사라질 때 probe·disconnect가 호출됩니다. SCSI, network, TTY처럼 다른 subsystem에 연결되는 driver는 그 subsystem의 userspace interface를 사용합니다.

MP3 player나 scanner처럼 맞는 subsystem이 없으면 USB subsystem에서 minor device number와 `file_operations`를 등록해 userspace가 직접 접근할 수 있습니다. 이 경우 fops와 minor는 필요하지만 다른 subsystem을 쓰는 driver에는 선택 사항입니다.

Module init은 `usb_register(&skel_driver)`를 호출하고 실패를 log·반환합니다. Module exit은 `usb_deregister()`로 반드시 등록을 해제합니다.

Hotplug 자동 module loading을 위해 `usb_device_id skel_table`과 `MODULE_DEVICE_TABLE(usb, skel_table)`을 제공합니다. `USB_DEVICE(vendor, product)` 뒤에는 빈 terminating entry가 필요하며 USB class 전체를 match하는 다른 macro는 `usb.h` 문서를 참고합니다.

USB driver 등록과 matching
`MODULE_DEVICE_TABLE`Hotplug alias 생성
`usb_register``usb_driver` 등록
`id_table` matchVendor·product 또는 class 확인
Device insertion`probe` 호출
Userspace access다른 subsystem 또는 minor·fops
Device removal`disconnect` 호출
Module exit`usb_deregister`

ID table을 기반으로 module loading과 interface binding callback이 이어집니다.


The first thing a Linux USB driver needs to do is register itself with
the Linux USB subsystem, giving it some information about which devices
the driver supports and which functions to call when a device supported
by the driver is inserted or removed from the system. All of this
information is passed to the USB subsystem in the :c:type:`usb_driver`
structure. The skeleton driver declares a :c:type:`usb_driver` as::

    static struct usb_driver skel_driver = {
            .name        = "skeleton",
            .probe       = skel_probe,
            .disconnect  = skel_disconnect,
            .suspend     = skel_suspend,
            .resume      = skel_resume,
            .pre_reset   = skel_pre_reset,
            .post_reset  = skel_post_reset,
            .id_table    = skel_table,
            .supports_autosuspend = 1,
    };


The variable name is a string that describes the driver. It is used in
informational messages printed to the system log. The probe and
disconnect function pointers are called when a device that matches the
information provided in the ``id_table`` variable is either seen or
removed.

The fops and minor variables are optional. Most USB drivers hook into
another kernel subsystem, such as the SCSI, network or TTY subsystem.
These types of drivers register themselves with the other kernel
subsystem, and any user-space interactions are provided through that
interface. But for drivers that do not have a matching kernel subsystem,
such as MP3 players or scanners, a method of interacting with user space
is needed. The USB subsystem provides a way to register a minor device
number and a set of :c:type:`file_operations` function pointers that enable
this user-space interaction. The skeleton driver needs this kind of
interface, so it provides a minor starting number and a pointer to its
:c:type:`file_operations` functions.

The USB driver is then registered with a call to usb_register(),
usually in the driver's init function, as shown here::

    static int __init usb_skel_init(void)
    {
            int result;

            /* register this driver with the USB subsystem */
            result = usb_register(&skel_driver);
            if (result < 0) {
                    pr_err("usb_register failed for the %s driver. Error number %d\n",
                           skel_driver.name, result);
                    return -1;
            }

            return 0;
    }
    module_init(usb_skel_init);


When the driver is unloaded from the system, it needs to deregister
itself with the USB subsystem. This is done with usb_deregister()
function::

    static void __exit usb_skel_exit(void)
    {
            /* deregister this driver with the USB subsystem */
            usb_deregister(&skel_driver);
    }
    module_exit(usb_skel_exit);


To enable the linux-hotplug system to load the driver automatically when
the device is plugged in, you need to create a ``MODULE_DEVICE_TABLE``.
The following code tells the hotplug scripts that this module supports a
single device with a specific vendor and product ID::

    /* table of devices that work with this driver */
    static struct usb_device_id skel_table [] = {
            { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
            { }                      /* Terminating entry */
    };
    MODULE_DEVICE_TABLE (usb, skel_table);


There are other macros that can be used in describing a struct
:c:type:`usb_device_id` for drivers that support a whole class of USB
drivers. See :ref:`usb.h <usb_header>` for more information on this.

Probe 검증, disconnect 정리와 open reference

136-179

등록한 device ID pattern과 맞는 장치가 bus에 연결되면 `skel_probe(struct usb_interface *interface, const struct usb_device_id *id)`가 호출됩니다. Driver는 실제로 수용 가능한 장치인지 다시 검증하고 성공하면 0, 초기화 실패나 부적합이면 `-ENOMEM`, `-ENODEV` 같은 error code를 반환합니다.

Skeleton probe는 bulk-in·bulk-out endpoint를 찾고 송수신 buffer를 만들며 device에 쓸 URB를 초기화합니다.

장치가 제거되면 disconnect가 private allocation을 정리하고 USB system에 남은 pending URB를 중단해야 합니다.

Binding 뒤 userspace가 device를 열면 `file_operations.open`이 먼저 호출됩니다. Driver는 `kref_get(&dev->kref)`로 private object 사용 reference를 늘리고 `file->private_data = dev`로 이후 read·write가 어느 device instance를 대상으로 하는지 알 수 있게 합니다.

Device operation 경계
EventDriver 책임
ID match`probe(interface, id)` 호출
Probe 검증지원 여부·endpoint 확인
초기화Buffer·write URB 준비
Open`kref_get`으로 object 수명 연장
File context`file->private_data`에 instance 저장
DisconnectPending URB 중단·private data 정리

Device operation
================

When a device is plugged into the USB bus that matches the device ID
pattern that your driver registered with the USB core, the probe
function is called. The :c:type:`usb_device` structure, interface number and
the interface ID are passed to the function::

    static int skel_probe(struct usb_interface *interface,
        const struct usb_device_id *id)


The driver now needs to verify that this device is actually one that it
can accept. If so, it returns 0. If not, or if any error occurs during
initialization, an errorcode (such as ``-ENOMEM`` or ``-ENODEV``) is
returned from the probe function.

In the skeleton driver, we determine what end points are marked as
bulk-in and bulk-out. We create buffers to hold the data that will be
sent and received from the device, and a USB urb to write data to the
device is initialized.

Conversely, when the device is removed from the USB bus, the disconnect
function is called with the device pointer. The driver needs to clean
any private data that has been allocated at this time and to shut down
any pending urbs that are in the USB system.

Now that the device is plugged into the system and the driver is bound
to the device, any of the functions in the :c:type:`file_operations` structure
that were passed to the USB subsystem will be called from a user program
trying to talk to the device. The first function called will be open, as
the program tries to open the device for I/O. We increment our private
usage count and save a pointer to our internal structure in the file
structure. This is done so that future calls to file operations will
enable the driver to determine which device the user is addressing. All
of this is done with the following code::

    /* increment our usage count for the device */
    kref_get(&dev->kref);

    /* save our object in the file's private structure */
    file->private_data = dev;

Bulk write URB 구성과 completion context

180-222

`skel_write`는 userspace data pointer와 길이를 받아 한 URB가 담을 수 있는 `MAX_TRANSFER`까지만 `writesize`로 선택합니다. `copy_from_user()`로 kernel buffer에 복사한 뒤 URB를 채웁니다.

`usb_fill_bulk_urb()`에는 target `usb_device`, `usb_sndbulkpipe()`로 만든 bulk-out pipe, buffer와 length, `skel_write_bulk_callback`, private context를 전달합니다. 이후 `usb_submit_urb(urb, GFP_KERNEL)`로 USB subsystem에 전송을 제출하고 오류를 log합니다.

Completion callback은 USB subsystem이 URB를 끝냈을 때 interrupt context에서 호출됩니다. 따라서 오래 걸리는 처리나 sleep을 피해야 하며 skeleton callback은 성공 여부만 보고하고 돌아옵니다.

Skeleton bulk write
`write()`User pointer·count 수신
`min_t``MAX_TRANSFER` 이하로 제한
`copy_from_user`Kernel transfer buffer 채움
`usb_fill_bulk_urb`Pipe·buffer·callback·context 설정
`usb_submit_urb`Asynchronous bulk-out 제출
Completion callbackInterrupt context에서 결과 처리

Userspace buffer를 하나의 asynchronous bulk URB로 전송합니다.

After the open function is called, the read and write functions are
called to receive and send data to the device. In the ``skel_write``
function, we receive a pointer to some data that the user wants to send
to the device and the size of the data. The function determines how much
data it can send to the device based on the size of the write urb it has
created (this size depends on the size of the bulk out end point that
the device has). Then it copies the data from user space to kernel
space, points the urb to the data and submits the urb to the USB
subsystem. This can be seen in the following code::

    /* we can only write as much as 1 urb will hold */
    size_t writesize = min_t(size_t, count, MAX_TRANSFER);

    /* copy the data from user space into our urb */
    copy_from_user(buf, user_buffer, writesize);

    /* set up our urb */
    usb_fill_bulk_urb(urb,
                      dev->udev,
                      usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                      buf,
                      writesize,
                      skel_write_bulk_callback,
                      dev);

    /* send the data out the bulk port */
    retval = usb_submit_urb(urb, GFP_KERNEL);
    if (retval) {
            dev_err(&dev->interface->dev,
                "%s - failed submitting write urb, error %d\n",
                __func__, retval);
    }


When the write urb is filled up with the proper information using the
:c:func:`usb_fill_bulk_urb` function, we point the urb's completion callback
to call our own ``skel_write_bulk_callback`` function. This function is
called when the urb is finished by the USB subsystem. The callback
function is called in interrupt context, so caution must be taken not to
do very much processing at that time. Our implementation of
``skel_write_bulk_callback`` merely reports if the urb was completed
successfully or not and then returns.

usb_bulk_msg 기반 동기 read

223-252

Skeleton read는 직접 URB와 completion callback을 만들지 않고 synchronous helper `usb_bulk_msg()`를 사용합니다. Receive bulk pipe, input buffer와 크기, 실제 byte count pointer, 5000 ms timeout을 전달합니다.

Timeout 안에 data가 없으면 helper가 실패와 error를 반환합니다. 성공하면 `copy_to_user()`로 받은 `count` byte를 userspace에 복사하고 복사 실패는 `-EFAULT`, 성공은 byte count를 반환합니다.

`usb_bulk_msg()`는 단발성 read·write에 편리하지만 지속적으로 전송해야 하는 device는 driver가 자체 URB를 구성해 USB subsystem에 반복 제출하는 방식이 권장됩니다.

동기 bulk read 결과
단계·결과처리
Pipe`usb_rcvbulkpipe()`
Transfer`usb_bulk_msg()`
Timeout5000 ms, data 없으면 error
성공실제 `count` byte 수신
Userspace copy 실패`-EFAULT`
지속 streaming자체 URB queue 권장

The read function works a bit differently from the write function in
that we do not use an urb to transfer data from the device to the
driver. Instead we call the :c:func:`usb_bulk_msg` function, which can be used
to send or receive data from a device without having to create urbs and
handle urb completion callback functions. We call the :c:func:`usb_bulk_msg`
function, giving it a buffer into which to place any data received from
the device and a timeout value. If the timeout period expires without
receiving any data from the device, the function will fail and return an
error message. This can be shown with the following code::

    /* do an immediate bulk read to get data from the device */
    retval = usb_bulk_msg (skel->dev,
                           usb_rcvbulkpipe (skel->dev,
                           skel->bulk_in_endpointAddr),
                           skel->bulk_in_buffer,
                           skel->bulk_in_size,
                           &count, 5000);
    /* if the read was successful, copy the data to user space */
    if (!retval) {
            if (copy_to_user (buffer, skel->bulk_in_buffer, count))
                    retval = -EFAULT;
            else
                    retval = count;
    }


The :c:func:`usb_bulk_msg` function can be very useful for doing single reads
or writes to a device; however, if you need to read or write constantly to
a device, it is recommended to set up your own urbs and submit them to
the USB subsystem.

Release, surprise removal과 object 정리

253-292

Userspace가 file handle을 닫으면 release가 호출되어 private usage count를 줄이고 pending write가 끝나기를 기다립니다. 원문 예제 조각은 `--skel->open_count`를 보여 줍니다.

USB device는 program이 사용 중이어도 언제든 제거될 수 있습니다. Driver는 진행 중 read·write를 중단하고 userspace에 장치가 사라졌음을 알려야 합니다.

`skel_delete()`는 bulk-in buffer를 free하고 coherent bulk-out buffer가 있으면 `usb_free_coherent()`로 DMA mapping과 함께 해제하며 write URB와 private object를 차례로 free합니다.

Open handle이 남아 있으면 disconnect는 `device_present` flag를 reset합니다. Read·write·release 등은 먼저 이 flag를 확인하고 장치가 없으면 `-ENODEV`를 반환합니다. 마지막 release는 device가 없고 open file도 끝난 시점에 disconnect가 즉시 하지 못한 cleanup을 수행합니다.

Surprise removal 수명주기
Device connected`device_present` true
Open fileUsage·kref 유지
Physical unplugDisconnect, pending I/O shutdown
Presence reset새 I/O는 `-ENODEV`
Open handle 유지Private object는 즉시 free하지 않음
Last releaseBuffer·DMA·URB·object 최종 정리

Disconnect와 열린 file reference가 공동으로 최종 free 시점을 결정합니다.


When the user program releases the file handle that it has been using to
talk to the device, the release function in the driver is called. In
this function we decrement our private usage count and wait for possible
pending writes::

    /* decrement our usage count for the device */
    --skel->open_count;


One of the more difficult problems that USB drivers must be able to
handle smoothly is the fact that the USB device may be removed from the
system at any point in time, even if a program is currently talking to
it. It needs to be able to shut down any current reads and writes and
notify the user-space programs that the device is no longer there. The
following code (function ``skel_delete``) is an example of how to do
this::

    static inline void skel_delete (struct usb_skel *dev)
    {
        kfree (dev->bulk_in_buffer);
        if (dev->bulk_out_buffer != NULL)
            usb_free_coherent (dev->udev, dev->bulk_out_size,
                dev->bulk_out_buffer,
                dev->write_urb->transfer_dma);
        usb_free_urb (dev->write_urb);
        kfree (dev);
    }


If a program currently has an open handle to the device, we reset the
flag ``device_present``. For every read, write, release and other
functions that expect a device to be present, the driver first checks
this flag to see if the device is still present. If not, it releases
that the device has disappeared, and a ``-ENODEV`` error is returned to the
user-space program. When the release function is eventually called, it
determines if there is no device and if not, it does the cleanup that
the ``skel_disconnect`` function normally does if there are no open files
on the device (see Listing 5).

Interrupt·isochronous 전송과 참고 자료

293-328

`usb-skeleton`에는 interrupt 또는 isochronous transfer 예제가 없습니다. Interrupt data는 몇 가지 작은 차이를 제외하면 bulk와 거의 같은 방식으로 전송합니다.

Isochronous data는 device와 연속 stream을 주고받는 방식이 다르므로 audio와 video camera driver가 좋은 구현 예입니다.

Skeleton과 현재 USB driver들을 함께 보면 초보 작성자도 작동하는 driver를 시작할 수 있고 linux-usb mailing list archive에서 추가 사례를 찾을 수 있습니다.

원문 Resources에는 Linux USB Project, Linux Hotplug Project, linux-usb archive, Linux USB device driver programming guide PDF, USB Home Page가 포함되며 URL을 원문 block에 보존했습니다.

전송 예제와 자료
항목권장 참고
Interrupt transferBulk URB pattern과 유사
Isochronous streamAudio·video camera driver
Skeleton`drivers/usb/usb-skeleton.c`
Mailing list`https://lore.kernel.org/linux-usb/`
Programming guideLMU Linux USB driver PDF
USB specification`https://www.usb.org`

Isochronous Data
================

This usb-skeleton driver does not have any examples of interrupt or
isochronous data being sent to or from the device. Interrupt data is
sent almost exactly as bulk data is, with a few minor exceptions.
Isochronous data works differently with continuous streams of data being
sent to or from the device. The audio and video camera drivers are very
good examples of drivers that handle isochronous data and will be useful
if you also need to do this.

Conclusion
==========

Writing Linux USB device drivers is not a difficult task as the
usb-skeleton driver shows. This driver, combined with the other current
USB drivers, should provide enough examples to help a beginning author
create a working driver in a minimal amount of time. The linux-usb-devel
mailing list archives also contain a lot of helpful information.

Resources
=========

The Linux USB Project:
http://www.linux-usb.org/

Linux Hotplug Project:
http://linux-hotplug.sourceforge.net/

linux-usb Mailing List Archives:
https://lore.kernel.org/linux-usb/

Programming Guide for Linux USB Device Drivers:
https://lmu.web.psi.ch/docu/manuals/software_manuals/linux_sl/usb_linux_programming_guide.pdf

USB Home Page: https://www.usb.org