aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/wusbcore
diff options
context:
space:
mode:
authorFelipe Zimmerle <felipe.zimmerle@indt.org.br>2008-09-17 11:34:42 -0400
committerDavid Vrabel <dv02@dv02pc01.europe.root.pri>2008-09-17 11:54:35 -0400
commitf1fa035f2bcb2b03cb90249e05ec2ae6927a7302 (patch)
tree410e7355c919c8c9384b9a3db497f83ca46170a9 /drivers/usb/wusbcore
parentc8cf2465fcfc16877f4f9e8dccc6b89b543fa2c5 (diff)
wusb: wusb-cbaf (CBA driver) sysfs ABI simplification
Simplify the sysfs ABI of the wusb-cbaf (Cable Based Association) driver: use one value per file and cause the write of the CHID to fetch the CDID (instead of requiring a separate read). Update the example wusb-cbaf script to work with this revised ABI. Signed-off-by: Felipe Zimmerle <felipe.zimmerle@indt.org.br> Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/usb/wusbcore')
-rw-r--r--drivers/usb/wusbcore/Kconfig23
-rw-r--r--drivers/usb/wusbcore/Makefile8
-rw-r--r--drivers/usb/wusbcore/cbaf.c521
3 files changed, 317 insertions, 235 deletions
diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index add077e5c5d0..4ea76693ad46 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -15,3 +15,26 @@ config USB_WUSB
15 15
16 To compile this support select Y (built in). It is safe to 16 To compile this support select Y (built in). It is safe to
17 select even if you don't have the hardware. 17 select even if you don't have the hardware.
18
19config USB_WUSB_CBAF
20 tristate "Support WUSB Cable Based Association (CBA)"
21 depends on USB
22 help
23 Some WUSB devices support Cable Based Association. It's used to
24 enable the secure communication between the host and the
25 device.
26
27 Enable this option if your WUSB device must to be connected
28 via wired USB before establishing a wireless link.
29
30 It is safe to select even if you don't have a compatible
31 hardware.
32
33config USB_WUSB_CBAF_DEBUG
34 bool "Enable CBA debug messages"
35 depends on USB_WUSB_CBAF
36 help
37 Say Y here if you want the CBA to produce a bunch of debug messages
38 to the system log. Select this if you are having a problem with
39 CBA support and want to see more of what is going on.
40
diff --git a/drivers/usb/wusbcore/Makefile b/drivers/usb/wusbcore/Makefile
index 7a4d00724039..75f1ade66258 100644
--- a/drivers/usb/wusbcore/Makefile
+++ b/drivers/usb/wusbcore/Makefile
@@ -1,5 +1,7 @@
1obj-$(CONFIG_USB_WUSB) += wusbcore.o wusb-cbaf.o 1obj-$(CONFIG_USB_WUSB) += wusbcore.o
2obj-$(CONFIG_USB_HWA_HCD) += wusb-wa.o 2obj-$(CONFIG_USB_HWA_HCD) += wusb-wa.o
3obj-$(CONFIG_USB_WUSB_CBAF) += wusb-cbaf.o
4
3 5
4wusbcore-objs := \ 6wusbcore-objs := \
5 crypto.o \ 7 crypto.o \
@@ -18,3 +20,7 @@ wusb-wa-objs := wa-hc.o \
18 wa-nep.o \ 20 wa-nep.o \
19 wa-rpipe.o \ 21 wa-rpipe.o \
20 wa-xfer.o 22 wa-xfer.o
23
24ifeq ($(CONFIG_USB_WUSB_CBAF_DEBUG),y)
25EXTRA_CFLAGS += -DDEBUG
26endif
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index 584eabe274b3..ab4788d1785a 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -4,6 +4,7 @@
4 * 4 *
5 * Copyright (C) 2006 Intel Corporation 5 * Copyright (C) 2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 10 * modify it under the terms of the GNU General Public License version
@@ -20,14 +21,13 @@
20 * 02110-1301, USA. 21 * 02110-1301, USA.
21 * 22 *
22 * 23 *
23 * WUSB devices have to be paired (authenticated in WUSB lingo) so 24 * WUSB devices have to be paired (associated in WUSB lingo) so
24 * that they can connect to the system. 25 * that they can connect to the system.
25 * 26 *
26 * One way of pairing is using CBA-Cable Based Authentication, devices 27 * One way of pairing is using CBA-Cable Based Association. First
27 * that can connect via wired or wireless USB. First time you plug 28 * time you plug the device with a cable, association is done between
28 * them with a cable, pairing is done between host and device and 29 * host and device and subsequent times, you can connect wirelessly
29 * subsequent times, you can connect wirelessly without having to 30 * without having to associate again. That's the idea.
30 * pair. That's the idea.
31 * 31 *
32 * This driver does nothing Earth shattering. It just provides an 32 * This driver does nothing Earth shattering. It just provides an
33 * interface to chat with the wire-connected device so we can get a 33 * interface to chat with the wire-connected device so we can get a
@@ -42,56 +42,49 @@
42 * 42 *
43 * The process goes like this: 43 * The process goes like this:
44 * 44 *
45 * 1. device plugs, cbaf is loaded, notifications happen 45 * 1. Device plugs, cbaf is loaded, notifications happen.
46 * 46 *
47 * 2. the connection manager sees a device with CBAF capability (the 47 * 2. The connection manager (CM) sees a device with CBAF capability
48 * wusb_{host_info,cdid,cc} files are in /sys/device/blah/OURDEVICE). 48 * (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE).
49 * 49 *
50 * 3. CM (connection manager) writes the CHID (host ID) and a host 50 * 3. The CM writes the host name, supported band groups, and the CHID
51 * name into the wusb_host_info file. This gets sent to the device. 51 * (host ID) into the wusb_host_name, wusb_host_band_groups and
52 * wusb_chid files. These get sent to the device and the CDID (if
53 * any) for this host is requested.
52 * 54 *
53 * 4. CM cats the wusb_cdid file; this asks the device if it has any 55 * 4. The CM can verify that the device's supported band groups
54 * CDID associated to the CHDI we just wrote before. If it does, it 56 * (wusb_device_band_groups) are compatible with the host.
55 * is printed, along with the device 'friendly name' and the band
56 * groups the device supports.
57 * 57 *
58 * 5. CM looks up its database 58 * 5. The CM reads the wusb_cdid file.
59 * 59 *
60 * 5.1 If it has a matching CHID,CDID entry, the device has been 60 * 6. The CM looks up its database
61 * authorized before (paired). Now we can optionally ask the user
62 * if he wants to allow the device to connect. Then we generate a
63 * new CDID and CK, send it to the device and update the database
64 * (writing to the wusb_cc file so they are uploaded to the device).
65 * 61 *
66 * 5.2 If the CDID is zero (or we didn't find a matching CDID in our 62 * 6.1 If it has a matching CHID,CDID entry, the device has been
67 * database), we assume the device is not known. We ask the user 63 * authorized before (paired) and nothing further needs to be
68 * if s/he wants to allow the device to be connected wirelessly 64 * done.
69 * to the system. If nope, nothing else is done (FIXME: maybe
70 * send a zero CDID to clean up our CHID?). If yes, we generate
71 * random CDID and CKs (and write them to the wusb_cc file so
72 * they are uploaded to the device).
73 * 65 *
74 * 6. device is unplugged 66 * 6.2 If the CDID is zero (or the CM doesn't find a matching CDID in
67 * its database), the device is assumed to be not known. The CM
68 * may associate the host with device by: writing a randomly
69 * generated CDID to wusb_cdid and then a random CK to wusb_ck
70 * (this uploads the new CC to the device).
75 * 71 *
76 * When the device tries to connect wirelessly, it will present it's 72 * CMD may choose to prompt the user before associating with a new
77 * CDID to the WUSB host controller with ID CHID, which will query the 73 * device.
78 * database. If found, the host will (with a 4way handshake) challenge
79 * the device to demonstrate it has the CK secret key (from our
80 * database) without actually exchanging it. Once satisfied, crypto
81 * keys are derived from the CK, the device is connected and all
82 * communication is crypted.
83 * 74 *
75 * 7. Device is unplugged.
84 * 76 *
85 * NOTES ABOUT THE IMPLEMENTATION 77 * When the device tries to connect wirelessly, it will present its
78 * CDID to the WUSB host controller. The CM will query the
79 * database. If the CHID/CDID pair found, it will (with a 4-way
80 * handshake) challenge the device to demonstrate it has the CK secret
81 * key (from our database) without actually exchanging it. Once
82 * satisfied, crypto keys are derived from the CK, the device is
83 * connected and all communication is encrypted.
86 * 84 *
87 * The descriptors sent back and forth use this horrible format from 85 * References:
88 * hell on which each field is actually a field ID, field length and 86 * [WUSB-AM] Association Models Supplement to the Certified Wireless
89 * then the field itself. How stupid can that get, taking into account 87 * Universal Serial Bus Specification, version 1.0.
90 * the structures are defined by the spec?? oh well.
91 *
92 *
93 * FIXME: we don't provide a way to tell the device the pairing failed
94 * (ie: send a CC_DATA_FAIL). Should add some day.
95 */ 88 */
96#include <linux/module.h> 89#include <linux/module.h>
97#include <linux/ctype.h> 90#include <linux/ctype.h>
@@ -105,9 +98,7 @@
105#include <linux/usb/wusb.h> 98#include <linux/usb/wusb.h>
106#include <linux/usb/association.h> 99#include <linux/usb/association.h>
107 100
108#undef D_LOCAL 101#define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */
109#define D_LOCAL 6
110#include <linux/uwb/debug.h>
111 102
112/* An instance of a Cable-Based-Association-Framework device */ 103/* An instance of a Cable-Based-Association-Framework device */
113struct cbaf { 104struct cbaf {
@@ -116,24 +107,27 @@ struct cbaf {
116 void *buffer; 107 void *buffer;
117 size_t buffer_size; 108 size_t buffer_size;
118 109
119 struct wusb_ckhdid chid;/* Host Information */ 110 struct wusb_ckhdid chid;
120 char host_name[65]; /* max length: 111 char host_name[CBA_NAME_LEN];
121 Assoc Models Suplement 1.0[T4-7] */
122 u16 host_band_groups; 112 u16 host_band_groups;
123 113
124 struct wusb_ckhdid cdid;/* Device Information */ 114 struct wusb_ckhdid cdid;
125 char device_name[65]; /* max length: 115 char device_name[CBA_NAME_LEN];
126 Assoc Models Suplement 1.0[T4-7] */
127 u16 device_band_groups; 116 u16 device_band_groups;
128 struct wusb_ckhdid ck; /* Connection Key */ 117
118 struct wusb_ckhdid ck;
129}; 119};
130 120
131/* 121/*
132 * Verify that a CBAF USB-interface has what we need 122 * Verify that a CBAF USB-interface has what we need
133 * 123 *
134 * (like we care, we are going to fail the enumeration if not :) 124 * According to [WUSB-AM], CBA devices should provide at least two
125 * interfaces:
126 * - RETRIEVE_HOST_INFO
127 * - ASSOCIATE
135 * 128 *
136 * FIXME: ugly function, need to split 129 * If the device doesn't provide these interfaces, we do not know how
130 * to deal with it.
137 */ 131 */
138static int cbaf_check(struct cbaf *cbaf) 132static int cbaf_check(struct cbaf *cbaf)
139{ 133{
@@ -143,8 +137,7 @@ static int cbaf_check(struct cbaf *cbaf)
143 struct wusb_cbaf_assoc_request *assoc_request; 137 struct wusb_cbaf_assoc_request *assoc_request;
144 size_t assoc_size; 138 size_t assoc_size;
145 void *itr, *top; 139 void *itr, *top;
146 unsigned ar_index; 140 int ar_rhi = 0, ar_assoc = 0;
147 int ar_rhi_idx = -1, ar_assoc_idx = -1;
148 141
149 result = usb_control_msg( 142 result = usb_control_msg(
150 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0), 143 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
@@ -153,93 +146,91 @@ static int cbaf_check(struct cbaf *cbaf)
153 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, 146 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
154 cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */); 147 cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
155 if (result < 0) { 148 if (result < 0) {
156 dev_err(dev, "cannot get available association types: %d\n", 149 dev_err(dev, "Cannot get available association types: %d\n",
157 result); 150 result);
158 goto error_get_assoc_types; 151 return result;
159 } 152 }
153
160 assoc_info = cbaf->buffer; 154 assoc_info = cbaf->buffer;
161 if (result < sizeof(*assoc_info)) { 155 if (result < sizeof(*assoc_info)) {
162 dev_err(dev, "not enough data to decode association info " 156 dev_err(dev, "Not enough data to decode association info "
163 "header (%zu vs %zu bytes required)\n", 157 "header (%zu vs %zu bytes required)\n",
164 (size_t)result, sizeof(*assoc_info)); 158 (size_t)result, sizeof(*assoc_info));
165 goto error_bad_header; 159 return result;
166 } 160 }
161
167 assoc_size = le16_to_cpu(assoc_info->Length); 162 assoc_size = le16_to_cpu(assoc_info->Length);
168 if (result < assoc_size) { 163 if (result < assoc_size) {
169 dev_err(dev, "not enough data to decode association info " 164 dev_err(dev, "Not enough data to decode association info "
170 "(%zu vs %zu bytes required)\n", 165 "(%zu vs %zu bytes required)\n",
171 (size_t)assoc_size, sizeof(*assoc_info)); 166 (size_t)assoc_size, sizeof(*assoc_info));
172 goto error_bad_data; 167 return result;
173 } 168 }
174 /* 169 /*
175 * From now on, we just verify, but won't error out unless we 170 * From now on, we just verify, but won't error out unless we
176 * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE} 171 * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
177 * types. 172 * types.
178 */ 173 */
179 ar_index = 0;
180 itr = cbaf->buffer + sizeof(*assoc_info); 174 itr = cbaf->buffer + sizeof(*assoc_info);
181 top = cbaf->buffer + assoc_size; 175 top = cbaf->buffer + assoc_size;
182 d_printf(1, dev, "Found %u association requests (%zu bytes)\n", 176 dev_dbg(dev, "Found %u association requests (%zu bytes)\n",
183 assoc_info->NumAssociationRequests, assoc_size); 177 assoc_info->NumAssociationRequests, assoc_size);
178
184 while (itr < top) { 179 while (itr < top) {
185 u16 ar_type, ar_subtype; 180 u16 ar_type, ar_subtype;
186 u32 ar_size; 181 u32 ar_size;
187 const char *ar_name; 182 const char *ar_name;
188 183
189 assoc_request = itr; 184 assoc_request = itr;
185
190 if (top - itr < sizeof(*assoc_request)) { 186 if (top - itr < sizeof(*assoc_request)) {
191 dev_err(dev, "not enough data to decode associaton " 187 dev_err(dev, "Not enough data to decode associaton "
192 "request (%zu vs %zu bytes needed)\n", 188 "request (%zu vs %zu bytes needed)\n",
193 top - itr, sizeof(*assoc_request)); 189 top - itr, sizeof(*assoc_request));
194 break; 190 break;
195 } 191 }
192
196 ar_type = le16_to_cpu(assoc_request->AssociationTypeId); 193 ar_type = le16_to_cpu(assoc_request->AssociationTypeId);
197 ar_subtype = le16_to_cpu(assoc_request->AssociationSubTypeId); 194 ar_subtype = le16_to_cpu(assoc_request->AssociationSubTypeId);
198 ar_size = le32_to_cpu(assoc_request->AssociationTypeInfoSize); 195 ar_size = le32_to_cpu(assoc_request->AssociationTypeInfoSize);
196 ar_name = "unknown";
197
199 switch (ar_type) { 198 switch (ar_type) {
200 case AR_TYPE_WUSB: 199 case AR_TYPE_WUSB:
201 /* Verify we have what is mandated by AMS1.0 */ 200 /* Verify we have what is mandated by [WUSB-AM]. */
202 switch (ar_subtype) { 201 switch (ar_subtype) {
203 case AR_TYPE_WUSB_RETRIEVE_HOST_INFO: 202 case AR_TYPE_WUSB_RETRIEVE_HOST_INFO:
204 ar_name = "retrieve_host_info"; 203 ar_name = "RETRIEVE_HOST_INFO";
205 ar_rhi_idx = ar_index; 204 ar_rhi = 1;
206 break; 205 break;
207 case AR_TYPE_WUSB_ASSOCIATE: 206 case AR_TYPE_WUSB_ASSOCIATE:
208 /* send assoc data */ 207 /* send assoc data */
209 ar_name = "associate"; 208 ar_name = "ASSOCIATE";
210 ar_assoc_idx = ar_index; 209 ar_assoc = 1;
211 break; 210 break;
212 default:
213 ar_name = "unknown";
214 }; 211 };
215 break; 212 break;
216 default:
217 ar_name = "unknown";
218 }; 213 };
219 d_printf(1, dev, "association request #%02u: 0x%04x/%04x " 214
215 dev_dbg(dev, "Association request #%02u: 0x%04x/%04x "
220 "(%zu bytes): %s\n", 216 "(%zu bytes): %s\n",
221 assoc_request->AssociationDataIndex, ar_type, 217 assoc_request->AssociationDataIndex, ar_type,
222 ar_subtype, (size_t)ar_size, ar_name); 218 ar_subtype, (size_t)ar_size, ar_name);
223 219
224 itr += sizeof(*assoc_request); 220 itr += sizeof(*assoc_request);
225 ar_index++;
226 } 221 }
227 if (ar_rhi_idx == -1) { 222
223 if (!ar_rhi) {
228 dev_err(dev, "Missing RETRIEVE_HOST_INFO association " 224 dev_err(dev, "Missing RETRIEVE_HOST_INFO association "
229 "request\n"); 225 "request\n");
230 goto error_bad_reqs; 226 return -EINVAL;
231 } 227 }
232 if (ar_assoc_idx == -1) { 228 if (!ar_assoc) {
233 dev_err(dev, "Missing ASSOCIATE association request\n"); 229 dev_err(dev, "Missing ASSOCIATE association request\n");
234 goto error_bad_reqs; 230 return -EINVAL;
235 } 231 }
236 return 0;
237 232
238error_bad_header: 233 return 0;
239error_bad_data:
240error_bad_reqs:
241error_get_assoc_types:
242 return -EINVAL;
243} 234}
244 235
245static const struct wusb_cbaf_host_info cbaf_host_info_defaults = { 236static const struct wusb_cbaf_host_info cbaf_host_info_defaults = {
@@ -256,6 +247,7 @@ static const struct wusb_cbaf_host_info cbaf_host_info_defaults = {
256static int cbaf_send_host_info(struct cbaf *cbaf) 247static int cbaf_send_host_info(struct cbaf *cbaf)
257{ 248{
258 struct wusb_cbaf_host_info *hi; 249 struct wusb_cbaf_host_info *hi;
250 size_t name_len;
259 size_t hi_size; 251 size_t hi_size;
260 252
261 hi = cbaf->buffer; 253 hi = cbaf->buffer;
@@ -263,11 +255,11 @@ static int cbaf_send_host_info(struct cbaf *cbaf)
263 *hi = cbaf_host_info_defaults; 255 *hi = cbaf_host_info_defaults;
264 hi->CHID = cbaf->chid; 256 hi->CHID = cbaf->chid;
265 hi->LangID = 0; /* FIXME: I guess... */ 257 hi->LangID = 0; /* FIXME: I guess... */
266 strncpy(hi->HostFriendlyName, cbaf->host_name, 258 strlcpy(hi->HostFriendlyName, cbaf->host_name, CBA_NAME_LEN);
267 hi->HostFriendlyName_hdr.len); 259 name_len = strlen(cbaf->host_name);
268 hi->HostFriendlyName_hdr.len = 260 hi->HostFriendlyName_hdr.len = cpu_to_le16(name_len);
269 cpu_to_le16(strlen(hi->HostFriendlyName)); 261 hi_size = sizeof(*hi) + name_len;
270 hi_size = sizeof(*hi) + strlen(hi->HostFriendlyName); 262
271 return usb_control_msg(cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0), 263 return usb_control_msg(cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
272 CBAF_REQ_SET_ASSOCIATION_RESPONSE, 264 CBAF_REQ_SET_ASSOCIATION_RESPONSE,
273 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 265 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
@@ -276,8 +268,47 @@ static int cbaf_send_host_info(struct cbaf *cbaf)
276 hi, hi_size, 1000 /* FIXME: arbitrary */); 268 hi, hi_size, 1000 /* FIXME: arbitrary */);
277} 269}
278 270
279/* Show current CHID info we have set from user space */ 271/*
280static ssize_t cbaf_wusb_host_info_show(struct device *dev, 272 * Get device's information (CDID) associated to CHID
273 *
274 * The device will return it's information (CDID, name, bandgroups)
275 * associated to the CHID we have set before, or 0 CDID and default
276 * name and bandgroup if no CHID set or unknown.
277 */
278static int cbaf_cdid_get(struct cbaf *cbaf)
279{
280 int result;
281 struct device *dev = &cbaf->usb_iface->dev;
282 struct wusb_cbaf_device_info *di;
283 size_t needed;
284
285 di = cbaf->buffer;
286 result = usb_control_msg(
287 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
288 CBAF_REQ_GET_ASSOCIATION_REQUEST,
289 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
290 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
291 di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
292 if (result < 0) {
293 dev_err(dev, "Cannot request device information: %d\n", result);
294 return result;
295 }
296
297 needed = result < sizeof(*di) ? sizeof(*di) : le32_to_cpu(di->Length);
298 if (result < needed) {
299 dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
300 "%zu bytes needed)\n", (size_t)result, needed);
301 return result;
302 }
303
304 strlcpy(cbaf->device_name, di->DeviceFriendlyName, CBA_NAME_LEN);
305 cbaf->cdid = di->CDID;
306 cbaf->device_band_groups = le16_to_cpu(di->BandGroups);
307
308 return 0;
309}
310
311static ssize_t cbaf_wusb_chid_show(struct device *dev,
281 struct device_attribute *attr, 312 struct device_attribute *attr,
282 char *buf) 313 char *buf)
283{ 314{
@@ -286,17 +317,10 @@ static ssize_t cbaf_wusb_host_info_show(struct device *dev,
286 char pr_chid[WUSB_CKHDID_STRSIZE]; 317 char pr_chid[WUSB_CKHDID_STRSIZE];
287 318
288 ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid); 319 ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid);
289 return scnprintf(buf, PAGE_SIZE, "CHID: %s\nName: %s\n", 320 return scnprintf(buf, PAGE_SIZE, "%s\n", pr_chid);
290 pr_chid, cbaf->host_name);
291} 321}
292 322
293/* 323static ssize_t cbaf_wusb_chid_store(struct device *dev,
294 * Get a host info CHID from user space and send it to the device.
295 *
296 * The user can recover a CC from the device associated to that CHID
297 * by cat'ing wusb_connection_context.
298 */
299static ssize_t cbaf_wusb_host_info_store(struct device *dev,
300 struct device_attribute *attr, 324 struct device_attribute *attr,
301 const char *buf, size_t size) 325 const char *buf, size_t size)
302{ 326{
@@ -308,8 +332,7 @@ static ssize_t cbaf_wusb_host_info_store(struct device *dev,
308 "%02hhx %02hhx %02hhx %02hhx " 332 "%02hhx %02hhx %02hhx %02hhx "
309 "%02hhx %02hhx %02hhx %02hhx " 333 "%02hhx %02hhx %02hhx %02hhx "
310 "%02hhx %02hhx %02hhx %02hhx " 334 "%02hhx %02hhx %02hhx %02hhx "
311 "%02hhx %02hhx %02hhx %02hhx " 335 "%02hhx %02hhx %02hhx %02hhx",
312 "%04hx %64s\n",
313 &cbaf->chid.data[0] , &cbaf->chid.data[1], 336 &cbaf->chid.data[0] , &cbaf->chid.data[1],
314 &cbaf->chid.data[2] , &cbaf->chid.data[3], 337 &cbaf->chid.data[2] , &cbaf->chid.data[3],
315 &cbaf->chid.data[4] , &cbaf->chid.data[5], 338 &cbaf->chid.data[4] , &cbaf->chid.data[5],
@@ -317,24 +340,79 @@ static ssize_t cbaf_wusb_host_info_store(struct device *dev,
317 &cbaf->chid.data[8] , &cbaf->chid.data[9], 340 &cbaf->chid.data[8] , &cbaf->chid.data[9],
318 &cbaf->chid.data[10], &cbaf->chid.data[11], 341 &cbaf->chid.data[10], &cbaf->chid.data[11],
319 &cbaf->chid.data[12], &cbaf->chid.data[13], 342 &cbaf->chid.data[12], &cbaf->chid.data[13],
320 &cbaf->chid.data[14], &cbaf->chid.data[15], 343 &cbaf->chid.data[14], &cbaf->chid.data[15]);
321 &cbaf->host_band_groups, cbaf->host_name); 344
322 if (result != 18) { 345 if (result != 16)
323 dev_err(dev, "Unrecognized CHID (need 16 8-bit hex digits, "
324 "a 16 bit hex band group mask "
325 "and a host name, got only %d)\n", (int)result);
326 return -EINVAL; 346 return -EINVAL;
327 } 347
328 result = cbaf_send_host_info(cbaf); 348 result = cbaf_send_host_info(cbaf);
329 if (result < 0) 349 if (result < 0)
330 dev_err(dev, "Couldn't send host information to device: %d\n", 350 return result;
331 (int)result); 351 result = cbaf_cdid_get(cbaf);
332 else 352 if (result < 0)
333 d_printf(1, dev, "HI sent, wusb_cc can be read now\n"); 353 return -result;
334 return result < 0 ? result : size; 354 return size;
355}
356static DEVICE_ATTR(wusb_chid, 0600, cbaf_wusb_chid_show, cbaf_wusb_chid_store);
357
358static ssize_t cbaf_wusb_host_name_show(struct device *dev,
359 struct device_attribute *attr,
360 char *buf)
361{
362 struct usb_interface *iface = to_usb_interface(dev);
363 struct cbaf *cbaf = usb_get_intfdata(iface);
364
365 return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->host_name);
366}
367
368static ssize_t cbaf_wusb_host_name_store(struct device *dev,
369 struct device_attribute *attr,
370 const char *buf, size_t size)
371{
372 ssize_t result;
373 struct usb_interface *iface = to_usb_interface(dev);
374 struct cbaf *cbaf = usb_get_intfdata(iface);
375
376 result = sscanf(buf, "%63s", cbaf->host_name);
377 if (result != 1)
378 return -EINVAL;
379
380 return size;
381}
382static DEVICE_ATTR(wusb_host_name, 0600, cbaf_wusb_host_name_show,
383 cbaf_wusb_host_name_store);
384
385static ssize_t cbaf_wusb_host_band_groups_show(struct device *dev,
386 struct device_attribute *attr,
387 char *buf)
388{
389 struct usb_interface *iface = to_usb_interface(dev);
390 struct cbaf *cbaf = usb_get_intfdata(iface);
391
392 return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->host_band_groups);
393}
394
395static ssize_t cbaf_wusb_host_band_groups_store(struct device *dev,
396 struct device_attribute *attr,
397 const char *buf, size_t size)
398{
399 ssize_t result;
400 struct usb_interface *iface = to_usb_interface(dev);
401 struct cbaf *cbaf = usb_get_intfdata(iface);
402 u16 band_groups = 0;
403
404 result = sscanf(buf, "%04hx", &band_groups);
405 if (result != 1)
406 return -EINVAL;
407
408 cbaf->host_band_groups = band_groups;
409
410 return size;
335} 411}
336static DEVICE_ATTR(wusb_host_info, 0600, cbaf_wusb_host_info_show, 412
337 cbaf_wusb_host_info_store); 413static DEVICE_ATTR(wusb_host_band_groups, 0600,
414 cbaf_wusb_host_band_groups_show,
415 cbaf_wusb_host_band_groups_store);
338 416
339static const struct wusb_cbaf_device_info cbaf_device_info_defaults = { 417static const struct wusb_cbaf_device_info cbaf_device_info_defaults = {
340 .Length_hdr = WUSB_AR_Length, 418 .Length_hdr = WUSB_AR_Length,
@@ -344,77 +422,72 @@ static const struct wusb_cbaf_device_info cbaf_device_info_defaults = {
344 .DeviceFriendlyName_hdr = WUSB_AR_DeviceFriendlyName, 422 .DeviceFriendlyName_hdr = WUSB_AR_DeviceFriendlyName,
345}; 423};
346 424
347/* 425static ssize_t cbaf_wusb_cdid_show(struct device *dev,
348 * Get device's information (CDID) associated to CHID 426 struct device_attribute *attr, char *buf)
349 *
350 * The device will return it's information (CDID, name, bandgroups)
351 * associated to the CHID we have set before, or 0 CDID and default
352 * name and bandgroup if no CHID set or unknown.
353 */
354static int cbaf_cdid_get(struct cbaf *cbaf)
355{ 427{
356 int result; 428 struct usb_interface *iface = to_usb_interface(dev);
357 struct device *dev = &cbaf->usb_iface->dev; 429 struct cbaf *cbaf = usb_get_intfdata(iface);
358 struct wusb_cbaf_device_info *di; 430 char pr_cdid[WUSB_CKHDID_STRSIZE];
359 size_t needed, dev_name_size;
360 431
361 di = cbaf->buffer; 432 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid);
362 result = usb_control_msg( 433 return scnprintf(buf, PAGE_SIZE, "%s\n", pr_cdid);
363 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
364 CBAF_REQ_GET_ASSOCIATION_REQUEST,
365 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
366 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
367 di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
368 if (result < 0) {
369 dev_err(dev, "Cannot request device information: %d\n", result);
370 goto error_req_di;
371 }
372 needed = result < sizeof(*di) ? sizeof(*di) : le32_to_cpu(di->Length);
373 if (result < needed) {
374 dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
375 "%zu bytes needed)\n", (size_t)result, needed);
376 goto error_bad_di;
377 }
378 cbaf->cdid = di->CDID;
379 dev_name_size = le16_to_cpu(di->DeviceFriendlyName_hdr.len);
380 dev_name_size = dev_name_size > 65 - 1 ? 65 - 1 : dev_name_size;
381 memcpy(cbaf->device_name, di->DeviceFriendlyName, dev_name_size);
382 cbaf->device_name[dev_name_size] = 0;
383 cbaf->device_band_groups = le16_to_cpu(di->BandGroups);
384 result = 0;
385error_req_di:
386error_bad_di:
387 return result;
388} 434}
389 435
390/* 436static ssize_t cbaf_wusb_cdid_store(struct device *dev,
391 * Get device information and print it to sysfs 437 struct device_attribute *attr,
392 * 438 const char *buf, size_t size)
393 * See cbaf_cdid_get()
394 */
395static ssize_t cbaf_wusb_cdid_show(struct device *dev,
396 struct device_attribute *attr, char *buf)
397{ 439{
398 ssize_t result; 440 ssize_t result;
399 struct usb_interface *iface = to_usb_interface(dev); 441 struct usb_interface *iface = to_usb_interface(dev);
400 struct cbaf *cbaf = usb_get_intfdata(iface); 442 struct cbaf *cbaf = usb_get_intfdata(iface);
401 char pr_cdid[WUSB_CKHDID_STRSIZE]; 443 struct wusb_ckhdid cdid;
402 444
403 result = cbaf_cdid_get(cbaf); 445 result = sscanf(buf,
404 if (result < 0) { 446 "%02hhx %02hhx %02hhx %02hhx "
405 dev_err(dev, "Cannot read device information: %d\n", 447 "%02hhx %02hhx %02hhx %02hhx "
406 (int)result); 448 "%02hhx %02hhx %02hhx %02hhx "
407 goto error_get_di; 449 "%02hhx %02hhx %02hhx %02hhx",
408 } 450 &cdid.data[0] , &cdid.data[1],
409 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid); 451 &cdid.data[2] , &cdid.data[3],
410 result = scnprintf(buf, PAGE_SIZE, 452 &cdid.data[4] , &cdid.data[5],
411 "CDID: %s\nName: %s\nBand_groups: 0x%04x\n", 453 &cdid.data[6] , &cdid.data[7],
412 pr_cdid, cbaf->device_name, 454 &cdid.data[8] , &cdid.data[9],
413 cbaf->device_band_groups); 455 &cdid.data[10], &cdid.data[11],
414error_get_di: 456 &cdid.data[12], &cdid.data[13],
415 return result; 457 &cdid.data[14], &cdid.data[15]);
458 if (result != 16)
459 return -EINVAL;
460
461 cbaf->cdid = cdid;
462
463 return size;
464}
465static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, cbaf_wusb_cdid_store);
466
467static ssize_t cbaf_wusb_device_band_groups_show(struct device *dev,
468 struct device_attribute *attr,
469 char *buf)
470{
471 struct usb_interface *iface = to_usb_interface(dev);
472 struct cbaf *cbaf = usb_get_intfdata(iface);
473
474 return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->device_band_groups);
475}
476
477static DEVICE_ATTR(wusb_device_band_groups, 0600,
478 cbaf_wusb_device_band_groups_show,
479 NULL);
480
481static ssize_t cbaf_wusb_device_name_show(struct device *dev,
482 struct device_attribute *attr,
483 char *buf)
484{
485 struct usb_interface *iface = to_usb_interface(dev);
486 struct cbaf *cbaf = usb_get_intfdata(iface);
487
488 return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->device_name);
416} 489}
417static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, NULL); 490static DEVICE_ATTR(wusb_device_name, 0600, cbaf_wusb_device_name_show, NULL);
418 491
419static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = { 492static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = {
420 .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, 493 .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId,
@@ -435,9 +508,7 @@ static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults = {
435}; 508};
436 509
437/* 510/*
438 * Send a new CC to the device 511 * Send a new CC to the device.
439 *
440 * So we update the CK and send the whole thing to the device
441 */ 512 */
442static int cbaf_cc_upload(struct cbaf *cbaf) 513static int cbaf_cc_upload(struct cbaf *cbaf)
443{ 514{
@@ -452,30 +523,25 @@ static int cbaf_cc_upload(struct cbaf *cbaf)
452 ccd->CDID = cbaf->cdid; 523 ccd->CDID = cbaf->cdid;
453 ccd->CK = cbaf->ck; 524 ccd->CK = cbaf->ck;
454 ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups); 525 ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups);
526
527 dev_dbg(dev, "Trying to upload CC:\n");
528 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID);
529 dev_dbg(dev, " CHID %s\n", pr_cdid);
530 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID);
531 dev_dbg(dev, " CDID %s\n", pr_cdid);
532 dev_dbg(dev, " Bandgroups 0x%04x\n", cbaf->host_band_groups);
533
455 result = usb_control_msg( 534 result = usb_control_msg(
456 cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0), 535 cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
457 CBAF_REQ_SET_ASSOCIATION_RESPONSE, 536 CBAF_REQ_SET_ASSOCIATION_RESPONSE,
458 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 537 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
459 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, 538 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
460 ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */); 539 ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */);
461 d_printf(1, dev, "Uploaded CC:\n"); 540
462 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID);
463 d_printf(1, dev, " CHID %s\n", pr_cdid);
464 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID);
465 d_printf(1, dev, " CDID %s\n", pr_cdid);
466 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CK);
467 d_printf(1, dev, " CK %s\n", pr_cdid);
468 d_printf(1, dev, " bandgroups 0x%04x\n", cbaf->host_band_groups);
469 return result; 541 return result;
470} 542}
471 543
472/* 544static ssize_t cbaf_wusb_ck_store(struct device *dev,
473 * Send a new CC to the device
474 *
475 * We take the CDID and CK from user space, the rest from the info we
476 * set with host_info.
477 */
478static ssize_t cbaf_wusb_cc_store(struct device *dev,
479 struct device_attribute *attr, 545 struct device_attribute *attr,
480 const char *buf, size_t size) 546 const char *buf, size_t size)
481{ 547{
@@ -484,23 +550,10 @@ static ssize_t cbaf_wusb_cc_store(struct device *dev,
484 struct cbaf *cbaf = usb_get_intfdata(iface); 550 struct cbaf *cbaf = usb_get_intfdata(iface);
485 551
486 result = sscanf(buf, 552 result = sscanf(buf,
487 "CDID: %02hhx %02hhx %02hhx %02hhx "
488 "%02hhx %02hhx %02hhx %02hhx "
489 "%02hhx %02hhx %02hhx %02hhx " 553 "%02hhx %02hhx %02hhx %02hhx "
490 "%02hhx %02hhx %02hhx %02hhx\n"
491 "CK: %02hhx %02hhx %02hhx %02hhx "
492 "%02hhx %02hhx %02hhx %02hhx " 554 "%02hhx %02hhx %02hhx %02hhx "
493 "%02hhx %02hhx %02hhx %02hhx " 555 "%02hhx %02hhx %02hhx %02hhx "
494 "%02hhx %02hhx %02hhx %02hhx\n", 556 "%02hhx %02hhx %02hhx %02hhx",
495 &cbaf->cdid.data[0] , &cbaf->cdid.data[1],
496 &cbaf->cdid.data[2] , &cbaf->cdid.data[3],
497 &cbaf->cdid.data[4] , &cbaf->cdid.data[5],
498 &cbaf->cdid.data[6] , &cbaf->cdid.data[7],
499 &cbaf->cdid.data[8] , &cbaf->cdid.data[9],
500 &cbaf->cdid.data[10], &cbaf->cdid.data[11],
501 &cbaf->cdid.data[12], &cbaf->cdid.data[13],
502 &cbaf->cdid.data[14], &cbaf->cdid.data[15],
503
504 &cbaf->ck.data[0] , &cbaf->ck.data[1], 557 &cbaf->ck.data[0] , &cbaf->ck.data[1],
505 &cbaf->ck.data[2] , &cbaf->ck.data[3], 558 &cbaf->ck.data[2] , &cbaf->ck.data[3],
506 &cbaf->ck.data[4] , &cbaf->ck.data[5], 559 &cbaf->ck.data[4] , &cbaf->ck.data[5],
@@ -509,25 +562,25 @@ static ssize_t cbaf_wusb_cc_store(struct device *dev,
509 &cbaf->ck.data[10], &cbaf->ck.data[11], 562 &cbaf->ck.data[10], &cbaf->ck.data[11],
510 &cbaf->ck.data[12], &cbaf->ck.data[13], 563 &cbaf->ck.data[12], &cbaf->ck.data[13],
511 &cbaf->ck.data[14], &cbaf->ck.data[15]); 564 &cbaf->ck.data[14], &cbaf->ck.data[15]);
512 if (result != 32) { 565 if (result != 16)
513 dev_err(dev, "Unrecognized CHID/CK (need 32 8-bit "
514 "hex digits, got only %d)\n", (int)result);
515 return -EINVAL; 566 return -EINVAL;
516 } 567
517 result = cbaf_cc_upload(cbaf); 568 result = cbaf_cc_upload(cbaf);
518 if (result < 0) 569 if (result < 0)
519 dev_err(dev, "Couldn't upload connection context: %d\n", 570 return result;
520 (int)result); 571
521 else 572 return size;
522 d_printf(1, dev, "Connection context uploaded\n");
523 return result < 0 ? result : size;
524} 573}
525static DEVICE_ATTR(wusb_cc, 0600, NULL, cbaf_wusb_cc_store); 574static DEVICE_ATTR(wusb_ck, 0600, NULL, cbaf_wusb_ck_store);
526 575
527static struct attribute *cbaf_dev_attrs[] = { 576static struct attribute *cbaf_dev_attrs[] = {
528 &dev_attr_wusb_host_info.attr, 577 &dev_attr_wusb_host_name.attr,
578 &dev_attr_wusb_host_band_groups.attr,
579 &dev_attr_wusb_chid.attr,
529 &dev_attr_wusb_cdid.attr, 580 &dev_attr_wusb_cdid.attr,
530 &dev_attr_wusb_cc.attr, 581 &dev_attr_wusb_device_name.attr,
582 &dev_attr_wusb_device_band_groups.attr,
583 &dev_attr_wusb_ck.attr,
531 NULL, 584 NULL,
532}; 585};
533 586
@@ -539,32 +592,33 @@ static struct attribute_group cbaf_dev_attr_group = {
539static int cbaf_probe(struct usb_interface *iface, 592static int cbaf_probe(struct usb_interface *iface,
540 const struct usb_device_id *id) 593 const struct usb_device_id *id)
541{ 594{
542 int result;
543 struct cbaf *cbaf; 595 struct cbaf *cbaf;
544 struct device *dev = &iface->dev; 596 struct device *dev = &iface->dev;
597 int result = -ENOMEM;
545 598
546 result = -ENOMEM;
547 cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL); 599 cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL);
548 if (cbaf == NULL) { 600 if (cbaf == NULL)
549 dev_err(dev, "Unable to allocate instance\n");
550 goto error_kzalloc; 601 goto error_kzalloc;
551 }
552 cbaf->buffer = kmalloc(512, GFP_KERNEL); 602 cbaf->buffer = kmalloc(512, GFP_KERNEL);
553 if (cbaf->buffer == NULL) 603 if (cbaf->buffer == NULL)
554 goto error_kmalloc_buffer; 604 goto error_kmalloc_buffer;
605
555 cbaf->buffer_size = 512; 606 cbaf->buffer_size = 512;
556 cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface)); 607 cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface));
557 cbaf->usb_iface = usb_get_intf(iface); 608 cbaf->usb_iface = usb_get_intf(iface);
558 result = cbaf_check(cbaf); 609 result = cbaf_check(cbaf);
559 if (result < 0) 610 if (result < 0) {
611 dev_err(dev, "This device is not WUSB-CBAF compliant"
612 "and is not supported yet.\n");
560 goto error_check; 613 goto error_check;
614 }
615
561 result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group); 616 result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group);
562 if (result < 0) { 617 if (result < 0) {
563 dev_err(dev, "Can't register sysfs attr group: %d\n", result); 618 dev_err(dev, "Can't register sysfs attr group: %d\n", result);
564 goto error_create_group; 619 goto error_create_group;
565 } 620 }
566 usb_set_intfdata(iface, cbaf); 621 usb_set_intfdata(iface, cbaf);
567 d_printf(2, dev, "CBA attached\n");
568 return 0; 622 return 0;
569 623
570error_create_group: 624error_create_group:
@@ -587,7 +641,6 @@ static void cbaf_disconnect(struct usb_interface *iface)
587 /* paranoia: clean up crypto keys */ 641 /* paranoia: clean up crypto keys */
588 memset(cbaf, 0, sizeof(*cbaf)); 642 memset(cbaf, 0, sizeof(*cbaf));
589 kfree(cbaf); 643 kfree(cbaf);
590 d_printf(1, dev, "CBA detached\n");
591} 644}
592 645
593static struct usb_device_id cbaf_id_table[] = { 646static struct usb_device_id cbaf_id_table[] = {