gpio: add support for the Diolan DLN-2 USB GPIO driver
[deliverable/linux.git] / drivers / mfd / dln2.c
CommitLineData
338a1281
OP
1/*
2 * Driver for the Diolan DLN-2 USB adapter
3 *
4 * Copyright (c) 2014 Intel Corporation
5 *
6 * Derived from:
7 * i2c-diolan-u2c.c
8 * Copyright (c) 2010-2011 Ericsson AB
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2.
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/types.h>
18#include <linux/slab.h>
19#include <linux/usb.h>
20#include <linux/i2c.h>
21#include <linux/mutex.h>
22#include <linux/platform_device.h>
23#include <linux/mfd/core.h>
24#include <linux/mfd/dln2.h>
25#include <linux/rculist.h>
26
27struct dln2_header {
28 __le16 size;
29 __le16 id;
30 __le16 echo;
31 __le16 handle;
32};
33
34struct dln2_response {
35 struct dln2_header hdr;
36 __le16 result;
37};
38
39#define DLN2_GENERIC_MODULE_ID 0x00
40#define DLN2_GENERIC_CMD(cmd) DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID)
41#define CMD_GET_DEVICE_VER DLN2_GENERIC_CMD(0x30)
42#define CMD_GET_DEVICE_SN DLN2_GENERIC_CMD(0x31)
43
44#define DLN2_HW_ID 0x200
45#define DLN2_USB_TIMEOUT 200 /* in ms */
46#define DLN2_MAX_RX_SLOTS 16
47#define DLN2_MAX_URBS 16
48#define DLN2_RX_BUF_SIZE 512
49
50enum dln2_handle {
51 DLN2_HANDLE_EVENT = 0, /* don't change, hardware defined */
52 DLN2_HANDLE_CTRL,
53 DLN2_HANDLE_GPIO,
54 DLN2_HANDLE_I2C,
55 DLN2_HANDLES
56};
57
58/*
59 * Receive context used between the receive demultiplexer and the transfer
60 * routine. While sending a request the transfer routine will look for a free
61 * receive context and use it to wait for a response and to receive the URB and
62 * thus the response data.
63 */
64struct dln2_rx_context {
65 /* completion used to wait for a response */
66 struct completion done;
67
68 /* if non-NULL the URB contains the response */
69 struct urb *urb;
70
71 /* if true then this context is used to wait for a response */
72 bool in_use;
73};
74
75/*
76 * Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the
77 * handle header field to identify the module in dln2_dev.mod_rx_slots and then
78 * the echo header field to index the slots field and find the receive context
79 * for a particular request.
80 */
81struct dln2_mod_rx_slots {
82 /* RX slots bitmap */
83 DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS);
84
85 /* used to wait for a free RX slot */
86 wait_queue_head_t wq;
87
88 /* used to wait for an RX operation to complete */
89 struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS];
90
91 /* avoid races between alloc/free_rx_slot and dln2_rx_transfer */
92 spinlock_t lock;
93};
94
95struct dln2_dev {
96 struct usb_device *usb_dev;
97 struct usb_interface *interface;
98 u8 ep_in;
99 u8 ep_out;
100
101 struct urb *rx_urb[DLN2_MAX_URBS];
102 void *rx_buf[DLN2_MAX_URBS];
103
104 struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES];
105
106 struct list_head event_cb_list;
107 spinlock_t event_cb_lock;
108
109 bool disconnect;
110 int active_transfers;
111 wait_queue_head_t disconnect_wq;
112 spinlock_t disconnect_lock;
113};
114
115struct dln2_event_cb_entry {
116 struct list_head list;
117 u16 id;
118 struct platform_device *pdev;
119 dln2_event_cb_t callback;
120};
121
122int dln2_register_event_cb(struct platform_device *pdev, u16 id,
123 dln2_event_cb_t event_cb)
124{
125 struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
126 struct dln2_event_cb_entry *i, *entry;
127 unsigned long flags;
128 int ret = 0;
129
130 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
131 if (!entry)
132 return -ENOMEM;
133
134 entry->id = id;
135 entry->callback = event_cb;
136 entry->pdev = pdev;
137
138 spin_lock_irqsave(&dln2->event_cb_lock, flags);
139
140 list_for_each_entry(i, &dln2->event_cb_list, list) {
141 if (i->id == id) {
142 ret = -EBUSY;
143 break;
144 }
145 }
146
147 if (!ret)
148 list_add_rcu(&entry->list, &dln2->event_cb_list);
149
150 spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
151
152 if (ret)
153 kfree(entry);
154
155 return ret;
156}
157EXPORT_SYMBOL(dln2_register_event_cb);
158
159void dln2_unregister_event_cb(struct platform_device *pdev, u16 id)
160{
161 struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
162 struct dln2_event_cb_entry *i;
163 unsigned long flags;
164 bool found = false;
165
166 spin_lock_irqsave(&dln2->event_cb_lock, flags);
167
168 list_for_each_entry(i, &dln2->event_cb_list, list) {
169 if (i->id == id) {
170 list_del_rcu(&i->list);
171 found = true;
172 break;
173 }
174 }
175
176 spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
177
178 if (found) {
179 synchronize_rcu();
180 kfree(i);
181 }
182}
183EXPORT_SYMBOL(dln2_unregister_event_cb);
184
185/*
186 * Returns true if a valid transfer slot is found. In this case the URB must not
187 * be resubmitted immediately in dln2_rx as we need the data when dln2_transfer
188 * is woke up. It will be resubmitted there.
189 */
190static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
191 u16 handle, u16 rx_slot)
192{
193 struct device *dev = &dln2->interface->dev;
194 struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
195 struct dln2_rx_context *rxc;
196 bool valid_slot = false;
197
198 rxc = &rxs->slots[rx_slot];
199
200 /*
201 * No need to disable interrupts as this lock is not taken in interrupt
202 * context elsewhere in this driver. This function (or its callers) are
203 * also not exported to other modules.
204 */
205 spin_lock(&rxs->lock);
206 if (rxc->in_use && !rxc->urb) {
207 rxc->urb = urb;
208 complete(&rxc->done);
209 valid_slot = true;
210 }
211 spin_unlock(&rxs->lock);
212
213 if (!valid_slot)
214 dev_warn(dev, "bad/late response %d/%d\n", handle, rx_slot);
215
216 return valid_slot;
217}
218
219static void dln2_run_event_callbacks(struct dln2_dev *dln2, u16 id, u16 echo,
220 void *data, int len)
221{
222 struct dln2_event_cb_entry *i;
223
224 rcu_read_lock();
225
226 list_for_each_entry_rcu(i, &dln2->event_cb_list, list) {
227 if (i->id == id) {
228 i->callback(i->pdev, echo, data, len);
229 break;
230 }
231 }
232
233 rcu_read_unlock();
234}
235
236static void dln2_rx(struct urb *urb)
237{
238 struct dln2_dev *dln2 = urb->context;
239 struct dln2_header *hdr = urb->transfer_buffer;
240 struct device *dev = &dln2->interface->dev;
241 u16 id, echo, handle, size;
242 u8 *data;
243 int len;
244 int err;
245
246 switch (urb->status) {
247 case 0:
248 /* success */
249 break;
250 case -ECONNRESET:
251 case -ENOENT:
252 case -ESHUTDOWN:
253 case -EPIPE:
254 /* this urb is terminated, clean up */
255 dev_dbg(dev, "urb shutting down with status %d\n", urb->status);
256 return;
257 default:
258 dev_dbg(dev, "nonzero urb status received %d\n", urb->status);
259 goto out;
260 }
261
262 if (urb->actual_length < sizeof(struct dln2_header)) {
263 dev_err(dev, "short response: %d\n", urb->actual_length);
264 goto out;
265 }
266
267 handle = le16_to_cpu(hdr->handle);
268 id = le16_to_cpu(hdr->id);
269 echo = le16_to_cpu(hdr->echo);
270 size = le16_to_cpu(hdr->size);
271
272 if (size != urb->actual_length) {
273 dev_err(dev, "size mismatch: handle %x cmd %x echo %x size %d actual %d\n",
274 handle, id, echo, size, urb->actual_length);
275 goto out;
276 }
277
278 if (handle >= DLN2_HANDLES) {
279 dev_warn(dev, "invalid handle %d\n", handle);
280 goto out;
281 }
282
283 data = urb->transfer_buffer + sizeof(struct dln2_header);
284 len = urb->actual_length - sizeof(struct dln2_header);
285
286 if (handle == DLN2_HANDLE_EVENT) {
287 dln2_run_event_callbacks(dln2, id, echo, data, len);
288 } else {
289 /* URB will be re-submitted in _dln2_transfer (free_rx_slot) */
290 if (dln2_transfer_complete(dln2, urb, handle, echo))
291 return;
292 }
293
294out:
295 err = usb_submit_urb(urb, GFP_ATOMIC);
296 if (err < 0)
297 dev_err(dev, "failed to resubmit RX URB: %d\n", err);
298}
299
300static void *dln2_prep_buf(u16 handle, u16 cmd, u16 echo, const void *obuf,
301 int *obuf_len, gfp_t gfp)
302{
303 int len;
304 void *buf;
305 struct dln2_header *hdr;
306
307 len = *obuf_len + sizeof(*hdr);
308 buf = kmalloc(len, gfp);
309 if (!buf)
310 return NULL;
311
312 hdr = (struct dln2_header *)buf;
313 hdr->id = cpu_to_le16(cmd);
314 hdr->size = cpu_to_le16(len);
315 hdr->echo = cpu_to_le16(echo);
316 hdr->handle = cpu_to_le16(handle);
317
318 memcpy(buf + sizeof(*hdr), obuf, *obuf_len);
319
320 *obuf_len = len;
321
322 return buf;
323}
324
325static int dln2_send_wait(struct dln2_dev *dln2, u16 handle, u16 cmd, u16 echo,
326 const void *obuf, int obuf_len)
327{
328 int ret = 0;
329 int len = obuf_len;
330 void *buf;
331 int actual;
332
333 buf = dln2_prep_buf(handle, cmd, echo, obuf, &len, GFP_KERNEL);
334 if (!buf)
335 return -ENOMEM;
336
337 ret = usb_bulk_msg(dln2->usb_dev,
338 usb_sndbulkpipe(dln2->usb_dev, dln2->ep_out),
339 buf, len, &actual, DLN2_USB_TIMEOUT);
340
341 kfree(buf);
342
343 return ret;
344}
345
346static bool find_free_slot(struct dln2_dev *dln2, u16 handle, int *slot)
347{
348 struct dln2_mod_rx_slots *rxs;
349 unsigned long flags;
350
351 if (dln2->disconnect) {
352 *slot = -ENODEV;
353 return true;
354 }
355
356 rxs = &dln2->mod_rx_slots[handle];
357
358 spin_lock_irqsave(&rxs->lock, flags);
359
360 *slot = find_first_zero_bit(rxs->bmap, DLN2_MAX_RX_SLOTS);
361
362 if (*slot < DLN2_MAX_RX_SLOTS) {
363 struct dln2_rx_context *rxc = &rxs->slots[*slot];
364
365 set_bit(*slot, rxs->bmap);
366 rxc->in_use = true;
367 }
368
369 spin_unlock_irqrestore(&rxs->lock, flags);
370
371 return *slot < DLN2_MAX_RX_SLOTS;
372}
373
374static int alloc_rx_slot(struct dln2_dev *dln2, u16 handle)
375{
376 int ret;
377 int slot;
378
379 /*
380 * No need to timeout here, the wait is bounded by the timeout in
381 * _dln2_transfer.
382 */
383 ret = wait_event_interruptible(dln2->mod_rx_slots[handle].wq,
384 find_free_slot(dln2, handle, &slot));
385 if (ret < 0)
386 return ret;
387
388 return slot;
389}
390
391static void free_rx_slot(struct dln2_dev *dln2, u16 handle, int slot)
392{
393 struct dln2_mod_rx_slots *rxs;
394 struct urb *urb = NULL;
395 unsigned long flags;
396 struct dln2_rx_context *rxc;
397
398 rxs = &dln2->mod_rx_slots[handle];
399
400 spin_lock_irqsave(&rxs->lock, flags);
401
402 clear_bit(slot, rxs->bmap);
403
404 rxc = &rxs->slots[slot];
405 rxc->in_use = false;
406 urb = rxc->urb;
407 rxc->urb = NULL;
408 reinit_completion(&rxc->done);
409
410 spin_unlock_irqrestore(&rxs->lock, flags);
411
412 if (urb) {
413 int err;
414 struct device *dev = &dln2->interface->dev;
415
416 err = usb_submit_urb(urb, GFP_KERNEL);
417 if (err < 0)
418 dev_err(dev, "failed to resubmit RX URB: %d\n", err);
419 }
420
421 wake_up_interruptible(&rxs->wq);
422}
423
424static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd,
425 const void *obuf, unsigned obuf_len,
426 void *ibuf, unsigned *ibuf_len)
427{
428 int ret = 0;
429 int rx_slot;
430 struct dln2_response *rsp;
431 struct dln2_rx_context *rxc;
432 struct device *dev = &dln2->interface->dev;
433 const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000;
434 struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
435
436 spin_lock(&dln2->disconnect_lock);
437 if (!dln2->disconnect)
438 dln2->active_transfers++;
439 else
440 ret = -ENODEV;
441 spin_unlock(&dln2->disconnect_lock);
442
443 if (ret)
444 return ret;
445
446 rx_slot = alloc_rx_slot(dln2, handle);
447 if (rx_slot < 0) {
448 ret = rx_slot;
449 goto out_decr;
450 }
451
452 ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len);
453 if (ret < 0) {
454 dev_err(dev, "USB write failed: %d\n", ret);
455 goto out_free_rx_slot;
456 }
457
458 rxc = &rxs->slots[rx_slot];
459
460 ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout);
461 if (ret <= 0) {
462 if (!ret)
463 ret = -ETIMEDOUT;
464 goto out_free_rx_slot;
465 }
466
467 if (dln2->disconnect) {
468 ret = -ENODEV;
469 goto out_free_rx_slot;
470 }
471
472 /* if we got here we know that the response header has been checked */
473 rsp = rxc->urb->transfer_buffer;
474
475 if (rsp->hdr.size < sizeof(*rsp)) {
476 ret = -EPROTO;
477 goto out_free_rx_slot;
478 }
479
480 if (le16_to_cpu(rsp->result) > 0x80) {
481 dev_dbg(dev, "%d received response with error %d\n",
482 handle, le16_to_cpu(rsp->result));
483 ret = -EREMOTEIO;
484 goto out_free_rx_slot;
485 }
486
487 if (!ibuf) {
488 ret = 0;
489 goto out_free_rx_slot;
490 }
491
492 if (*ibuf_len > rsp->hdr.size - sizeof(*rsp))
493 *ibuf_len = rsp->hdr.size - sizeof(*rsp);
494
495 memcpy(ibuf, rsp + 1, *ibuf_len);
496
497out_free_rx_slot:
498 free_rx_slot(dln2, handle, rx_slot);
499out_decr:
500 spin_lock(&dln2->disconnect_lock);
501 dln2->active_transfers--;
502 spin_unlock(&dln2->disconnect_lock);
503 if (dln2->disconnect)
504 wake_up(&dln2->disconnect_wq);
505
506 return ret;
507}
508
509int dln2_transfer(struct platform_device *pdev, u16 cmd,
510 const void *obuf, unsigned obuf_len,
511 void *ibuf, unsigned *ibuf_len)
512{
513 struct dln2_platform_data *dln2_pdata;
514 struct dln2_dev *dln2;
515 u16 handle;
516
517 dln2 = dev_get_drvdata(pdev->dev.parent);
518 dln2_pdata = dev_get_platdata(&pdev->dev);
519 handle = dln2_pdata->handle;
520
521 return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf,
522 ibuf_len);
523}
524EXPORT_SYMBOL(dln2_transfer);
525
526static int dln2_check_hw(struct dln2_dev *dln2)
527{
528 int ret;
529 __le32 hw_type;
530 int len = sizeof(hw_type);
531
532 ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER,
533 NULL, 0, &hw_type, &len);
534 if (ret < 0)
535 return ret;
536 if (len < sizeof(hw_type))
537 return -EREMOTEIO;
538
539 if (le32_to_cpu(hw_type) != DLN2_HW_ID) {
540 dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n",
541 le32_to_cpu(hw_type));
542 return -ENODEV;
543 }
544
545 return 0;
546}
547
548static int dln2_print_serialno(struct dln2_dev *dln2)
549{
550 int ret;
551 __le32 serial_no;
552 int len = sizeof(serial_no);
553 struct device *dev = &dln2->interface->dev;
554
555 ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0,
556 &serial_no, &len);
557 if (ret < 0)
558 return ret;
559 if (len < sizeof(serial_no))
560 return -EREMOTEIO;
561
562 dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no));
563
564 return 0;
565}
566
567static int dln2_hw_init(struct dln2_dev *dln2)
568{
569 int ret;
570
571 ret = dln2_check_hw(dln2);
572 if (ret < 0)
573 return ret;
574
575 return dln2_print_serialno(dln2);
576}
577
578static void dln2_free_rx_urbs(struct dln2_dev *dln2)
579{
580 int i;
581
582 for (i = 0; i < DLN2_MAX_URBS; i++) {
583 usb_kill_urb(dln2->rx_urb[i]);
584 usb_free_urb(dln2->rx_urb[i]);
585 kfree(dln2->rx_buf[i]);
586 }
587}
588
589static void dln2_free(struct dln2_dev *dln2)
590{
591 dln2_free_rx_urbs(dln2);
592 usb_put_dev(dln2->usb_dev);
593 kfree(dln2);
594}
595
596static int dln2_setup_rx_urbs(struct dln2_dev *dln2,
597 struct usb_host_interface *hostif)
598{
599 int i;
600 int ret;
601 const int rx_max_size = DLN2_RX_BUF_SIZE;
602 struct device *dev = &dln2->interface->dev;
603
604 for (i = 0; i < DLN2_MAX_URBS; i++) {
605 dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL);
606 if (!dln2->rx_buf[i])
607 return -ENOMEM;
608
609 dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
610 if (!dln2->rx_urb[i])
611 return -ENOMEM;
612
613 usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev,
614 usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in),
615 dln2->rx_buf[i], rx_max_size, dln2_rx, dln2);
616
617 ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL);
618 if (ret < 0) {
619 dev_err(dev, "failed to submit RX URB: %d\n", ret);
620 return ret;
621 }
622 }
623
624 return 0;
625}
626
627static struct dln2_platform_data dln2_pdata_gpio = {
628 .handle = DLN2_HANDLE_GPIO,
629};
630
631/* Only one I2C port seems to be supported on current hardware */
632static struct dln2_platform_data dln2_pdata_i2c = {
633 .handle = DLN2_HANDLE_I2C,
634 .port = 0,
635};
636
637static const struct mfd_cell dln2_devs[] = {
638 {
639 .name = "dln2-gpio",
640 .platform_data = &dln2_pdata_gpio,
641 .pdata_size = sizeof(struct dln2_platform_data),
642 },
643 {
644 .name = "dln2-i2c",
645 .platform_data = &dln2_pdata_i2c,
646 .pdata_size = sizeof(struct dln2_platform_data),
647 },
648};
649
650static void dln2_disconnect(struct usb_interface *interface)
651{
652 struct dln2_dev *dln2 = usb_get_intfdata(interface);
653 int i, j;
654
655 /* don't allow starting new transfers */
656 spin_lock(&dln2->disconnect_lock);
657 dln2->disconnect = true;
658 spin_unlock(&dln2->disconnect_lock);
659
660 /* cancel in progress transfers */
661 for (i = 0; i < DLN2_HANDLES; i++) {
662 struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i];
663 unsigned long flags;
664
665 spin_lock_irqsave(&rxs->lock, flags);
666
667 /* cancel all response waiters */
668 for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) {
669 struct dln2_rx_context *rxc = &rxs->slots[j];
670
671 if (rxc->in_use)
672 complete(&rxc->done);
673 }
674
675 spin_unlock_irqrestore(&rxs->lock, flags);
676 }
677
678 /* wait for transfers to end */
679 wait_event(dln2->disconnect_wq, !dln2->active_transfers);
680
681 mfd_remove_devices(&interface->dev);
682
683 dln2_free(dln2);
684}
685
686static int dln2_probe(struct usb_interface *interface,
687 const struct usb_device_id *usb_id)
688{
689 struct usb_host_interface *hostif = interface->cur_altsetting;
690 struct device *dev = &interface->dev;
691 struct dln2_dev *dln2;
692 int ret;
693 int i, j;
694
695 if (hostif->desc.bInterfaceNumber != 0 ||
696 hostif->desc.bNumEndpoints < 2)
697 return -ENODEV;
698
699 dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL);
700 if (!dln2)
701 return -ENOMEM;
702
703 dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
704 dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
705 dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface));
706 dln2->interface = interface;
707 usb_set_intfdata(interface, dln2);
708 init_waitqueue_head(&dln2->disconnect_wq);
709
710 for (i = 0; i < DLN2_HANDLES; i++) {
711 init_waitqueue_head(&dln2->mod_rx_slots[i].wq);
712 spin_lock_init(&dln2->mod_rx_slots[i].lock);
713 for (j = 0; j < DLN2_MAX_RX_SLOTS; j++)
714 init_completion(&dln2->mod_rx_slots[i].slots[j].done);
715 }
716
717 spin_lock_init(&dln2->event_cb_lock);
718 spin_lock_init(&dln2->disconnect_lock);
719 INIT_LIST_HEAD(&dln2->event_cb_list);
720
721 ret = dln2_setup_rx_urbs(dln2, hostif);
722 if (ret)
723 goto out_cleanup;
724
725 ret = dln2_hw_init(dln2);
726 if (ret < 0) {
727 dev_err(dev, "failed to initialize hardware\n");
728 goto out_cleanup;
729 }
730
731 ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs));
732 if (ret != 0) {
733 dev_err(dev, "failed to add mfd devices to core\n");
734 goto out_cleanup;
735 }
736
737 return 0;
738
739out_cleanup:
740 dln2_free(dln2);
741
742 return ret;
743}
744
745static const struct usb_device_id dln2_table[] = {
746 { USB_DEVICE(0xa257, 0x2013) },
747 { }
748};
749
750MODULE_DEVICE_TABLE(usb, dln2_table);
751
752static struct usb_driver dln2_driver = {
753 .name = "dln2",
754 .probe = dln2_probe,
755 .disconnect = dln2_disconnect,
756 .id_table = dln2_table,
757};
758
759module_usb_driver(dln2_driver);
760
761MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>");
762MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter");
763MODULE_LICENSE("GPL v2");
This page took 0.051869 seconds and 5 git commands to generate.