Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Felipe Zimmerle and committed by
David Vrabel
f1fa035f c8cf2465

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