aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/atm/xusbatm.c
diff options
context:
space:
mode:
authorDuncan Sands <duncan.sands@math.u-psud.fr>2005-05-11 14:17:09 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-27 17:43:57 -0400
commit0bb3cf37df1b59a1fed079e7f8f140ef9ec73130 (patch)
tree3f50092a6b61bec712c44f9c2f2ccfa06799244a /drivers/usb/atm/xusbatm.c
parent1b0e614652344a2d39eb336f3dc07651782883bf (diff)
[PATCH] USB ATM: generic DSL modem driver xusbatm
Doesn't do any firmware loading etc, just transmission and reception. The user needs to take care of modem initialization, and load the module with parameters giving the endpoints to use and so forth. Signed-off-by: Duncan Sands <baldrick@free.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/atm/xusbatm.c')
-rw-r--r--drivers/usb/atm/xusbatm.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
new file mode 100644
index 000000000000..7fe7fb484d10
--- /dev/null
+++ b/drivers/usb/atm/xusbatm.c
@@ -0,0 +1,196 @@
1/******************************************************************************
2 * xusbatm.c - dumb usbatm-based driver for modems initialized in userspace
3 *
4 * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 ******************************************************************************/
21
22#include <linux/module.h>
23#include <linux/netdevice.h> /* FIXME: required by linux/etherdevice.h */
24#include <linux/etherdevice.h> /* for random_ether_addr() */
25
26#include "usbatm.h"
27
28
29#define XUSBATM_DRIVERS_MAX 8
30
31#define XUSBATM_PARM(name, type, parmtype, desc) \
32 static type name[XUSBATM_DRIVERS_MAX]; \
33 static int num_##name; \
34 module_param_array(name, parmtype, &num_##name, 0444); \
35 MODULE_PARM_DESC(name, desc)
36
37XUSBATM_PARM(vendor, unsigned short, ushort, "USB device vendor");
38XUSBATM_PARM(product, unsigned short, ushort, "USB device product");
39
40XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number");
41XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
42XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
43XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
44
45static const char xusbatm_driver_name[] = "xusbatm";
46
47static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX];
48static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
49static struct usb_driver xusbatm_usb_driver;
50
51static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)
52{
53 int i, j;
54
55 for (i = 0; i < intf->num_altsetting; i++) {
56 struct usb_host_interface *alt = intf->altsetting;
57 for (j = 0; j < alt->desc.bNumEndpoints; j++)
58 if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)
59 return 1;
60 }
61 return 0;
62}
63
64static int xusbatm_bind(struct usbatm_data *usbatm_instance,
65 struct usb_interface *intf, const struct usb_device_id *id,
66 int *need_heavy_init)
67{
68 struct usb_device *usb_dev = interface_to_usbdev(intf);
69 int drv_ix = id - xusbatm_usb_ids;
70 int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);
71 int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);
72 u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
73 int i, ret;
74
75 usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x"
76 " rx: ep %#x padd %d tx: ep %#x padd %d\n",
77 __func__, drv_ix, vendor[drv_ix], product[drv_ix],
78 rx_endpoint[drv_ix], rx_padding[drv_ix],
79 tx_endpoint[drv_ix], tx_padding[drv_ix]);
80
81 if (!rx_ep_present && !tx_ep_present) {
82 usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
83 __func__, intf->altsetting->desc.bInterfaceNumber,
84 rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
85 return -ENODEV;
86 }
87
88 if (rx_ep_present && tx_ep_present)
89 return 0;
90
91 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
92 struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
93
94 if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
95 ret = usb_driver_claim_interface(&xusbatm_usb_driver,
96 cur_if, usbatm_instance);
97 if (!ret)
98 usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n",
99 __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
100 return ret;
101 }
102 }
103
104 usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n",
105 __func__, searched_ep);
106 return -ENODEV;
107}
108
109static void xusbatm_unbind(struct usbatm_data *usbatm_instance,
110 struct usb_interface *intf)
111{
112 struct usb_device *usb_dev = interface_to_usbdev(intf);
113 int i;
114 usb_dbg(usbatm_instance, "%s entered\n", __func__);
115
116 for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
117 struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
118 usb_set_intfdata(cur_if, NULL);
119 usb_driver_release_interface(&xusbatm_usb_driver, cur_if);
120 }
121}
122
123static int xusbatm_atm_start(struct usbatm_data *usbatm_instance,
124 struct atm_dev *atm_dev)
125{
126 atm_dbg(usbatm_instance, "%s entered\n", __func__);
127
128 /* use random MAC as we've no way to get it from the device */
129 random_ether_addr(atm_dev->esi);
130
131 return 0;
132}
133
134
135static int xusbatm_usb_probe(struct usb_interface *intf,
136 const struct usb_device_id *id)
137{
138 return usbatm_usb_probe(intf, id,
139 xusbatm_drivers + (id - xusbatm_usb_ids));
140}
141
142static struct usb_driver xusbatm_usb_driver = {
143 .owner = THIS_MODULE,
144 .name = xusbatm_driver_name,
145 .probe = xusbatm_usb_probe,
146 .disconnect = usbatm_usb_disconnect,
147 .id_table = xusbatm_usb_ids
148};
149
150static int __init xusbatm_init(void)
151{
152 int i;
153
154 dbg("xusbatm_init");
155
156 if (!num_vendor ||
157 num_vendor != num_product ||
158 num_vendor != num_rx_endpoint ||
159 num_vendor != num_tx_endpoint) {
160 warn("malformed module parameters");
161 return -EINVAL;
162 }
163
164 for (i = 0; i < num_vendor; i++) {
165 xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
166 xusbatm_usb_ids[i].idVendor = vendor[i];
167 xusbatm_usb_ids[i].idProduct = product[i];
168
169
170 xusbatm_drivers[i].owner = THIS_MODULE;
171 xusbatm_drivers[i].driver_name = xusbatm_driver_name;
172 xusbatm_drivers[i].bind = xusbatm_bind;
173 xusbatm_drivers[i].unbind = xusbatm_unbind;
174 xusbatm_drivers[i].atm_start = xusbatm_atm_start;
175 xusbatm_drivers[i].in = rx_endpoint[i];
176 xusbatm_drivers[i].out = tx_endpoint[i];
177 xusbatm_drivers[i].rx_padding = rx_padding[i];
178 xusbatm_drivers[i].tx_padding = tx_padding[i];
179 }
180
181 return usb_register(&xusbatm_usb_driver);
182}
183module_init(xusbatm_init);
184
185static void __exit xusbatm_exit(void)
186{
187 dbg("xusbatm_exit entered");
188
189 usb_deregister(&xusbatm_usb_driver);
190}
191module_exit(xusbatm_exit);
192
193MODULE_AUTHOR("Roman Kagan, Duncan Sands");
194MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");
195MODULE_LICENSE("GPL");
196MODULE_VERSION("0.1");