Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * USB IR Dongle driver | |
3 | * | |
4 | * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) | |
5 | * Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com) | |
f4a4cbb2 | 6 | * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) |
1da177e4 LT |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This driver allows a USB IrDA device to be used as a "dumb" serial device. | |
14 | * This can be useful if you do not have access to a full IrDA stack on the | |
15 | * other side of the connection. If you do have an IrDA stack on both devices, | |
16 | * please use the usb-irda driver, as it contains the proper error checking and | |
17 | * other goodness of a full IrDA stack. | |
18 | * | |
19 | * Portions of this driver were taken from drivers/net/irda/irda-usb.c, which | |
20 | * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli | |
21 | * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com> | |
22 | * | |
e0d795e4 FB |
23 | * See Documentation/usb/usb-serial.txt for more information on using this |
24 | * driver | |
25 | * | |
26 | * 2008_Jun_02 Felipe Balbi <me@felipebalbi.com> | |
27 | * Introduced common header to be used also in USB Gadget Framework. | |
28 | * Still needs some other style fixes. | |
1da177e4 | 29 | * |
8eb04cf3 | 30 | * 2007_Jun_21 Alan Cox <alan@lxorguk.ukuu.org.uk> |
a6ea438b AC |
31 | * Minimal cleanups for some of the driver problens and tty layer abuse. |
32 | * Still needs fixing to allow multiple dongles. | |
33 | * | |
1da177e4 LT |
34 | * 2002_Mar_07 greg kh |
35 | * moved some needed structures and #define values from the | |
36 | * net/irda/irda-usb.h file into our file, as we don't want to depend on | |
37 | * that codebase compiling correctly :) | |
38 | * | |
39 | * 2002_Jan_14 gb | |
40 | * Added module parameter to force specific number of XBOFs. | |
41 | * Added ir_xbof_change(). | |
42 | * Reorganized read_bulk_callback error handling. | |
43 | * Switched from FILL_BULK_URB() to usb_fill_bulk_urb(). | |
44 | * | |
45 | * 2001_Nov_08 greg kh | |
46 | * Changed the irda_usb_find_class_desc() function based on comments and | |
47 | * code from Martin Diehl. | |
48 | * | |
49 | * 2001_Nov_01 greg kh | |
50 | * Added support for more IrDA USB devices. | |
51 | * Added support for zero packet. Added buffer override paramater, so | |
52 | * users can transfer larger packets at once if they wish. Both patches | |
53 | * came from Dag Brattli <dag@obexcode.com>. | |
54 | * | |
55 | * 2001_Oct_07 greg kh | |
56 | * initial version released. | |
57 | */ | |
58 | ||
1da177e4 LT |
59 | #include <linux/kernel.h> |
60 | #include <linux/errno.h> | |
61 | #include <linux/init.h> | |
62 | #include <linux/slab.h> | |
63 | #include <linux/tty.h> | |
64 | #include <linux/tty_driver.h> | |
65 | #include <linux/tty_flip.h> | |
66 | #include <linux/module.h> | |
67 | #include <linux/spinlock.h> | |
e0d795e4 | 68 | #include <linux/uaccess.h> |
1da177e4 | 69 | #include <linux/usb.h> |
a969888c | 70 | #include <linux/usb/serial.h> |
e0d795e4 | 71 | #include <linux/usb/irda.h> |
1da177e4 LT |
72 | |
73 | /* | |
74 | * Version Information | |
75 | */ | |
f4a4cbb2 JH |
76 | #define DRIVER_VERSION "v0.5" |
77 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Johan Hovold <jhovold@gmail.com>" | |
1da177e4 LT |
78 | #define DRIVER_DESC "USB IR Dongle driver" |
79 | ||
1da177e4 LT |
80 | static int debug; |
81 | ||
82 | /* if overridden by the user, then use their value for the size of the read and | |
83 | * write urbs */ | |
84 | static int buffer_size; | |
e0d795e4 | 85 | |
1da177e4 LT |
86 | /* if overridden by the user, then use the specified number of XBOFs */ |
87 | static int xbof = -1; | |
88 | ||
95da310e | 89 | static int ir_startup (struct usb_serial *serial); |
a509a7e4 | 90 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); |
f4a4cbb2 JH |
91 | static int ir_prepare_write_buffer(struct usb_serial_port *port, |
92 | void *dest, size_t size); | |
93 | static void ir_process_read_urb(struct urb *urb); | |
95da310e AC |
94 | static void ir_set_termios(struct tty_struct *tty, |
95 | struct usb_serial_port *port, struct ktermios *old_termios); | |
1da177e4 | 96 | |
a6ea438b | 97 | /* Not that this lot means you can only have one per system */ |
e0d795e4 FB |
98 | static u8 ir_baud; |
99 | static u8 ir_xbof; | |
100 | static u8 ir_add_bof; | |
1da177e4 | 101 | |
7d40d7e8 | 102 | static const struct usb_device_id ir_id_table[] = { |
1da177e4 LT |
103 | { USB_DEVICE(0x050f, 0x0180) }, /* KC Technology, KC-180 */ |
104 | { USB_DEVICE(0x08e9, 0x0100) }, /* XTNDAccess */ | |
105 | { USB_DEVICE(0x09c4, 0x0011) }, /* ACTiSys ACT-IR2000U */ | |
e0d795e4 | 106 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) }, |
1da177e4 LT |
107 | { } /* Terminating entry */ |
108 | }; | |
109 | ||
e0d795e4 | 110 | MODULE_DEVICE_TABLE(usb, ir_id_table); |
1da177e4 LT |
111 | |
112 | static struct usb_driver ir_driver = { | |
e0d795e4 FB |
113 | .name = "ir-usb", |
114 | .probe = usb_serial_probe, | |
115 | .disconnect = usb_serial_disconnect, | |
116 | .id_table = ir_id_table, | |
117 | .no_dynamic_id = 1, | |
1da177e4 LT |
118 | }; |
119 | ||
ea65370d | 120 | static struct usb_serial_driver ir_device = { |
e0d795e4 FB |
121 | .driver = { |
122 | .owner = THIS_MODULE, | |
123 | .name = "ir-usb", | |
18fcac35 | 124 | }, |
e0d795e4 FB |
125 | .description = "IR Dongle", |
126 | .usb_driver = &ir_driver, | |
127 | .id_table = ir_id_table, | |
128 | .num_ports = 1, | |
129 | .set_termios = ir_set_termios, | |
130 | .attach = ir_startup, | |
131 | .open = ir_open, | |
f4a4cbb2 JH |
132 | .prepare_write_buffer = ir_prepare_write_buffer, |
133 | .process_read_urb = ir_process_read_urb, | |
1da177e4 LT |
134 | }; |
135 | ||
e0d795e4 | 136 | static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc) |
1da177e4 LT |
137 | { |
138 | dbg("bLength=%x", desc->bLength); | |
139 | dbg("bDescriptorType=%x", desc->bDescriptorType); | |
e0d795e4 | 140 | dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision)); |
1da177e4 LT |
141 | dbg("bmDataSize=%x", desc->bmDataSize); |
142 | dbg("bmWindowSize=%x", desc->bmWindowSize); | |
143 | dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime); | |
e0d795e4 | 144 | dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate)); |
1da177e4 LT |
145 | dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs); |
146 | dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff); | |
147 | dbg("bMaxUnicastList=%x", desc->bMaxUnicastList); | |
148 | } | |
149 | ||
150 | /*------------------------------------------------------------------*/ | |
151 | /* | |
152 | * Function irda_usb_find_class_desc(dev, ifnum) | |
153 | * | |
154 | * Returns instance of IrDA class descriptor, or NULL if not found | |
155 | * | |
156 | * The class descriptor is some extra info that IrDA USB devices will | |
157 | * offer to us, describing their IrDA characteristics. We will use that in | |
158 | * irda_usb_init_qos() | |
159 | * | |
160 | * Based on the same function in drivers/net/irda/irda-usb.c | |
161 | */ | |
e0d795e4 FB |
162 | static struct usb_irda_cs_descriptor * |
163 | irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum) | |
1da177e4 | 164 | { |
e0d795e4 | 165 | struct usb_irda_cs_descriptor *desc; |
1da177e4 | 166 | int ret; |
e0d795e4 FB |
167 | |
168 | desc = kzalloc(sizeof(*desc), GFP_KERNEL); | |
169 | if (!desc) | |
1da177e4 | 170 | return NULL; |
e0d795e4 FB |
171 | |
172 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
173 | USB_REQ_CS_IRDA_GET_CLASS_DESC, | |
1da177e4 LT |
174 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
175 | 0, ifnum, desc, sizeof(*desc), 1000); | |
e0d795e4 | 176 | |
441b62c1 | 177 | dbg("%s - ret=%d", __func__, ret); |
1da177e4 LT |
178 | if (ret < sizeof(*desc)) { |
179 | dbg("%s - class descriptor read %s (%d)", | |
441b62c1 | 180 | __func__, |
e0d795e4 | 181 | (ret < 0) ? "failed" : "too short", |
1da177e4 LT |
182 | ret); |
183 | goto error; | |
184 | } | |
e0d795e4 | 185 | if (desc->bDescriptorType != USB_DT_CS_IRDA) { |
441b62c1 | 186 | dbg("%s - bad class descriptor type", __func__); |
1da177e4 LT |
187 | goto error; |
188 | } | |
e0d795e4 | 189 | |
1da177e4 LT |
190 | irda_usb_dump_class_desc(desc); |
191 | return desc; | |
e0d795e4 | 192 | |
1da177e4 LT |
193 | error: |
194 | kfree(desc); | |
195 | return NULL; | |
196 | } | |
197 | ||
1da177e4 LT |
198 | static u8 ir_xbof_change(u8 xbof) |
199 | { | |
200 | u8 result; | |
e0d795e4 | 201 | |
1da177e4 | 202 | /* reference irda-usb.c */ |
e0d795e4 FB |
203 | switch (xbof) { |
204 | case 48: | |
205 | result = 0x10; | |
206 | break; | |
207 | case 28: | |
208 | case 24: | |
209 | result = 0x20; | |
210 | break; | |
211 | default: | |
212 | case 12: | |
213 | result = 0x30; | |
214 | break; | |
215 | case 5: | |
216 | case 6: | |
217 | result = 0x40; | |
218 | break; | |
219 | case 3: | |
220 | result = 0x50; | |
221 | break; | |
222 | case 2: | |
223 | result = 0x60; | |
224 | break; | |
225 | case 1: | |
226 | result = 0x70; | |
227 | break; | |
228 | case 0: | |
229 | result = 0x80; | |
230 | break; | |
1da177e4 | 231 | } |
e0d795e4 | 232 | |
1da177e4 LT |
233 | return(result); |
234 | } | |
235 | ||
e0d795e4 | 236 | static int ir_startup(struct usb_serial *serial) |
1da177e4 | 237 | { |
e0d795e4 | 238 | struct usb_irda_cs_descriptor *irda_desc; |
1da177e4 | 239 | |
e0d795e4 FB |
240 | irda_desc = irda_usb_find_class_desc(serial->dev, 0); |
241 | if (!irda_desc) { | |
242 | dev_err(&serial->dev->dev, | |
243 | "IRDA class descriptor not found, device not bound\n"); | |
1da177e4 LT |
244 | return -ENODEV; |
245 | } | |
246 | ||
e0d795e4 | 247 | dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s", |
441b62c1 | 248 | __func__, |
e0d795e4 FB |
249 | (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "", |
250 | (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "", | |
251 | (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "", | |
252 | (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "", | |
253 | (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "", | |
254 | (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "", | |
255 | (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "", | |
256 | (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "", | |
257 | (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : ""); | |
258 | ||
259 | switch (irda_desc->bmAdditionalBOFs) { | |
260 | case USB_IRDA_AB_48: | |
261 | ir_add_bof = 48; | |
262 | break; | |
263 | case USB_IRDA_AB_24: | |
264 | ir_add_bof = 24; | |
265 | break; | |
266 | case USB_IRDA_AB_12: | |
267 | ir_add_bof = 12; | |
268 | break; | |
269 | case USB_IRDA_AB_6: | |
270 | ir_add_bof = 6; | |
271 | break; | |
272 | case USB_IRDA_AB_3: | |
273 | ir_add_bof = 3; | |
274 | break; | |
275 | case USB_IRDA_AB_2: | |
276 | ir_add_bof = 2; | |
277 | break; | |
278 | case USB_IRDA_AB_1: | |
279 | ir_add_bof = 1; | |
280 | break; | |
281 | case USB_IRDA_AB_0: | |
282 | ir_add_bof = 0; | |
283 | break; | |
284 | default: | |
285 | break; | |
1da177e4 LT |
286 | } |
287 | ||
e0d795e4 | 288 | kfree(irda_desc); |
1da177e4 | 289 | |
e0d795e4 | 290 | return 0; |
1da177e4 LT |
291 | } |
292 | ||
a509a7e4 | 293 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) |
1da177e4 | 294 | { |
f4a4cbb2 | 295 | int i; |
1da177e4 | 296 | |
441b62c1 | 297 | dbg("%s - port %d", __func__, port->number); |
1da177e4 | 298 | |
f4a4cbb2 JH |
299 | for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) |
300 | port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; | |
e0d795e4 | 301 | |
f4a4cbb2 JH |
302 | /* Start reading from the device */ |
303 | return usb_serial_generic_open(tty, port); | |
1da177e4 LT |
304 | } |
305 | ||
f4a4cbb2 JH |
306 | static int ir_prepare_write_buffer(struct usb_serial_port *port, |
307 | void *dest, size_t size) | |
1da177e4 | 308 | { |
f4a4cbb2 | 309 | unsigned char *buf = dest; |
e421fe97 | 310 | int count; |
1da177e4 LT |
311 | |
312 | /* | |
313 | * The first byte of the packet we send to the device contains an | |
e0d795e4 | 314 | * inbound header which indicates an additional number of BOFs and |
1da177e4 LT |
315 | * a baud rate change. |
316 | * | |
317 | * See section 5.4.2.2 of the USB IrDA spec. | |
318 | */ | |
f4a4cbb2 | 319 | *buf = ir_xbof | ir_baud; |
1da177e4 | 320 | |
e421fe97 | 321 | count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, |
f4a4cbb2 | 322 | &port->lock); |
e421fe97 | 323 | return count + 1; |
1da177e4 LT |
324 | } |
325 | ||
f4a4cbb2 | 326 | static void ir_process_read_urb(struct urb *urb) |
1da177e4 | 327 | { |
cdc97792 | 328 | struct usb_serial_port *port = urb->context; |
1da177e4 | 329 | unsigned char *data = urb->transfer_buffer; |
f4a4cbb2 | 330 | struct tty_struct *tty; |
1da177e4 | 331 | |
f4a4cbb2 JH |
332 | if (!urb->actual_length) |
333 | return; | |
334 | /* | |
335 | * The first byte of the packet we get from the device | |
336 | * contains a busy indicator and baud rate change. | |
337 | * See section 5.4.1.2 of the USB IrDA spec. | |
338 | */ | |
339 | if (*data & 0x0f) | |
340 | ir_baud = *data & 0x0f; | |
1da177e4 | 341 | |
f4a4cbb2 JH |
342 | if (urb->actual_length == 1) |
343 | return; | |
344 | ||
345 | tty = tty_port_tty_get(&port->port); | |
346 | if (!tty) | |
347 | return; | |
348 | tty_insert_flip_string(tty, data + 1, urb->actual_length - 1); | |
349 | tty_flip_buffer_push(tty); | |
350 | tty_kref_put(tty); | |
1da177e4 LT |
351 | } |
352 | ||
df66e8a2 JH |
353 | static void ir_set_termios_callback(struct urb *urb) |
354 | { | |
355 | struct usb_serial_port *port = urb->context; | |
356 | int status = urb->status; | |
357 | ||
358 | dbg("%s - port %d", __func__, port->number); | |
359 | ||
360 | kfree(urb->transfer_buffer); | |
361 | ||
362 | if (status) | |
363 | dbg("%s - non-zero urb status: %d", __func__, status); | |
364 | } | |
365 | ||
95da310e AC |
366 | static void ir_set_termios(struct tty_struct *tty, |
367 | struct usb_serial_port *port, struct ktermios *old_termios) | |
1da177e4 | 368 | { |
df66e8a2 | 369 | struct urb *urb; |
1da177e4 | 370 | unsigned char *transfer_buffer; |
1da177e4 | 371 | int result; |
a6ea438b AC |
372 | speed_t baud; |
373 | int ir_baud; | |
1da177e4 | 374 | |
441b62c1 | 375 | dbg("%s - port %d", __func__, port->number); |
1da177e4 | 376 | |
95da310e | 377 | baud = tty_get_baud_rate(tty); |
a6ea438b AC |
378 | |
379 | /* | |
380 | * FIXME, we should compare the baud request against the | |
381 | * capability stated in the IR header that we got in the | |
382 | * startup function. | |
383 | */ | |
384 | ||
385 | switch (baud) { | |
e0d795e4 FB |
386 | case 2400: |
387 | ir_baud = USB_IRDA_BR_2400; | |
388 | break; | |
389 | case 9600: | |
390 | ir_baud = USB_IRDA_BR_9600; | |
391 | break; | |
392 | case 19200: | |
393 | ir_baud = USB_IRDA_BR_19200; | |
394 | break; | |
395 | case 38400: | |
396 | ir_baud = USB_IRDA_BR_38400; | |
397 | break; | |
398 | case 57600: | |
399 | ir_baud = USB_IRDA_BR_57600; | |
400 | break; | |
401 | case 115200: | |
402 | ir_baud = USB_IRDA_BR_115200; | |
403 | break; | |
404 | case 576000: | |
405 | ir_baud = USB_IRDA_BR_576000; | |
406 | break; | |
407 | case 1152000: | |
408 | ir_baud = USB_IRDA_BR_1152000; | |
409 | break; | |
410 | case 4000000: | |
411 | ir_baud = USB_IRDA_BR_4000000; | |
412 | break; | |
413 | default: | |
414 | ir_baud = USB_IRDA_BR_9600; | |
415 | baud = 9600; | |
1da177e4 LT |
416 | } |
417 | ||
a6ea438b AC |
418 | if (xbof == -1) |
419 | ir_xbof = ir_xbof_change(ir_add_bof); | |
420 | else | |
421 | ir_xbof = ir_xbof_change(xbof) ; | |
1da177e4 | 422 | |
df66e8a2 JH |
423 | /* Only speed changes are supported */ |
424 | tty_termios_copy_hw(tty->termios, old_termios); | |
425 | tty_encode_baud_rate(tty, baud, baud); | |
426 | ||
427 | /* | |
a6ea438b AC |
428 | * send the baud change out on an "empty" data packet |
429 | */ | |
df66e8a2 JH |
430 | urb = usb_alloc_urb(0, GFP_KERNEL); |
431 | if (!urb) { | |
432 | dev_err(&port->dev, "%s - no more urbs\n", __func__); | |
433 | return; | |
434 | } | |
435 | transfer_buffer = kmalloc(1, GFP_KERNEL); | |
436 | if (!transfer_buffer) { | |
437 | dev_err(&port->dev, "%s - out of memory\n", __func__); | |
438 | goto err_buf; | |
439 | } | |
440 | ||
a6ea438b | 441 | *transfer_buffer = ir_xbof | ir_baud; |
1da177e4 | 442 | |
e0d795e4 | 443 | usb_fill_bulk_urb( |
df66e8a2 | 444 | urb, |
a6ea438b | 445 | port->serial->dev, |
e0d795e4 FB |
446 | usb_sndbulkpipe(port->serial->dev, |
447 | port->bulk_out_endpointAddress), | |
df66e8a2 | 448 | transfer_buffer, |
a6ea438b | 449 | 1, |
df66e8a2 | 450 | ir_set_termios_callback, |
a6ea438b AC |
451 | port); |
452 | ||
df66e8a2 | 453 | urb->transfer_flags = URB_ZERO_PACKET; |
a6ea438b | 454 | |
df66e8a2 JH |
455 | result = usb_submit_urb(urb, GFP_KERNEL); |
456 | if (result) { | |
457 | dev_err(&port->dev, "%s - failed to submit urb: %d\n", | |
458 | __func__, result); | |
459 | goto err_subm; | |
460 | } | |
560aac22 | 461 | |
df66e8a2 JH |
462 | usb_free_urb(urb); |
463 | ||
464 | return; | |
465 | err_subm: | |
466 | kfree(transfer_buffer); | |
467 | err_buf: | |
468 | usb_free_urb(urb); | |
1da177e4 LT |
469 | } |
470 | ||
e0d795e4 | 471 | static int __init ir_init(void) |
1da177e4 LT |
472 | { |
473 | int retval; | |
e0d795e4 | 474 | |
6f6ed696 JH |
475 | if (buffer_size) { |
476 | ir_device.bulk_in_size = buffer_size; | |
477 | ir_device.bulk_out_size = buffer_size; | |
478 | } | |
479 | ||
1da177e4 LT |
480 | retval = usb_serial_register(&ir_device); |
481 | if (retval) | |
482 | goto failed_usb_serial_register; | |
e0d795e4 | 483 | |
1da177e4 | 484 | retval = usb_register(&ir_driver); |
e0d795e4 | 485 | if (retval) |
1da177e4 | 486 | goto failed_usb_register; |
e0d795e4 | 487 | |
c197a8db GKH |
488 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
489 | DRIVER_DESC "\n"); | |
e0d795e4 | 490 | |
1da177e4 | 491 | return 0; |
e0d795e4 | 492 | |
1da177e4 LT |
493 | failed_usb_register: |
494 | usb_serial_deregister(&ir_device); | |
e0d795e4 | 495 | |
1da177e4 LT |
496 | failed_usb_serial_register: |
497 | return retval; | |
498 | } | |
499 | ||
e0d795e4 | 500 | static void __exit ir_exit(void) |
1da177e4 | 501 | { |
e0d795e4 FB |
502 | usb_deregister(&ir_driver); |
503 | usb_serial_deregister(&ir_device); | |
1da177e4 LT |
504 | } |
505 | ||
506 | ||
507 | module_init(ir_init); | |
508 | module_exit(ir_exit); | |
509 | ||
510 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
511 | MODULE_DESCRIPTION(DRIVER_DESC); | |
512 | MODULE_LICENSE("GPL"); | |
513 | ||
514 | module_param(debug, bool, S_IRUGO | S_IWUSR); | |
515 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | |
516 | module_param(xbof, int, 0); | |
517 | MODULE_PARM_DESC(xbof, "Force specific number of XBOFs"); | |
518 | module_param(buffer_size, int, 0); | |
519 | MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); | |
520 |