cbaf.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * Wireless USB - Cable Based Association
  3. *
  4. *
  5. * Copyright (C) 2006 Intel Corporation
  6. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  7. *
  8. * 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. * 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. * 02110-1301, USA.
  21. *
  22. *
  23. * WUSB devices have to be paired (authenticated in WUSB lingo) so
  24. * that they can connect to the system.
  25. *
  26. * One way of pairing is using CBA-Cable Based Authentication, devices
  27. * that can connect via wired or wireless USB. First time you plug
  28. * them with a cable, pairing is done between host and device and
  29. * subsequent times, you can connect wirelessly without having to
  30. * pair. That's the idea.
  31. *
  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
  34. * CDID (device ID) that might have been previously associated to a
  35. * CHID (host ID) and to set up a new <CHID,CDID,CK> triplet
  36. * (connection context), with the CK being the secret, or connection
  37. * key. This is the pairing data.
  38. *
  39. * When a device with the CBA capability connects, the probe routine
  40. * just creates a bunch of sysfs files that a user space enumeration
  41. * manager uses to allow it to connect wirelessly to the system or not.
  42. *
  43. * The process goes like this:
  44. *
  45. * 1. device plugs, cbaf is loaded, notifications happen
  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).
  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.
  52. *
  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.
  57. *
  58. * 5. CM looks up its database
  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).
  65. *
  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).
  73. *
  74. * 6. device is unplugged
  75. *
  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.
  83. *
  84. *
  85. * NOTES ABOUT THE IMPLEMENTATION
  86. *
  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.
  95. */
  96. #include <linux/module.h>
  97. #include <linux/ctype.h>
  98. #include <linux/version.h>
  99. #include <linux/usb.h>
  100. #include <linux/interrupt.h>
  101. #include <linux/delay.h>
  102. #include <linux/random.h>
  103. #include <linux/mutex.h>
  104. #include <linux/uwb.h>
  105. #include <linux/usb/wusb.h>
  106. #include <linux/usb/association.h>
  107. #undef D_LOCAL
  108. #define D_LOCAL 6
  109. #include <linux/uwb/debug.h>
  110. /* An instance of a Cable-Based-Association-Framework device */
  111. struct cbaf {
  112. struct usb_device *usb_dev;
  113. struct usb_interface *usb_iface;
  114. void *buffer;
  115. size_t buffer_size;
  116. struct wusb_ckhdid chid;/* Host Information */
  117. char host_name[65]; /* max length:
  118. Assoc Models Suplement 1.0[T4-7] */
  119. u16 host_band_groups;
  120. struct wusb_ckhdid cdid;/* Device Information */
  121. char device_name[65]; /* max length:
  122. Assoc Models Suplement 1.0[T4-7] */
  123. u16 device_band_groups;
  124. struct wusb_ckhdid ck; /* Connection Key */
  125. };
  126. /*
  127. * Verify that a CBAF USB-interface has what we need
  128. *
  129. * (like we care, we are going to fail the enumeration if not :)
  130. *
  131. * FIXME: ugly function, need to split
  132. */
  133. static int cbaf_check(struct cbaf *cbaf)
  134. {
  135. int result;
  136. struct device *dev = &cbaf->usb_iface->dev;
  137. struct wusb_cbaf_assoc_info *assoc_info;
  138. struct wusb_cbaf_assoc_request *assoc_request;
  139. size_t assoc_size;
  140. void *itr, *top;
  141. unsigned ar_index;
  142. int ar_rhi_idx = -1, ar_assoc_idx = -1;
  143. result = usb_control_msg(
  144. cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
  145. CBAF_REQ_GET_ASSOCIATION_INFORMATION,
  146. USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  147. 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
  148. cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
  149. if (result < 0) {
  150. dev_err(dev, "cannot get available association types: %d\n",
  151. result);
  152. goto error_get_assoc_types;
  153. }
  154. assoc_info = cbaf->buffer;
  155. if (result < sizeof(*assoc_info)) {
  156. dev_err(dev, "not enough data to decode association info "
  157. "header (%zu vs %zu bytes required)\n",
  158. (size_t)result, sizeof(*assoc_info));
  159. goto error_bad_header;
  160. }
  161. assoc_size = le16_to_cpu(assoc_info->Length);
  162. if (result < assoc_size) {
  163. dev_err(dev, "not enough data to decode association info "
  164. "(%zu vs %zu bytes required)\n",
  165. (size_t)assoc_size, sizeof(*assoc_info));
  166. goto error_bad_data;
  167. }
  168. /*
  169. * From now on, we just verify, but won't error out unless we
  170. * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
  171. * types.
  172. */
  173. ar_index = 0;
  174. itr = cbaf->buffer + sizeof(*assoc_info);
  175. top = cbaf->buffer + assoc_size;
  176. d_printf(1, dev, "Found %u association requests (%zu bytes)\n",
  177. assoc_info->NumAssociationRequests, assoc_size);
  178. while (itr < top) {
  179. u16 ar_type, ar_subtype;
  180. u32 ar_size;
  181. const char *ar_name;
  182. assoc_request = itr;
  183. if (top - itr < sizeof(*assoc_request)) {
  184. dev_err(dev, "not enough data to decode associaton "
  185. "request (%zu vs %zu bytes needed)\n",
  186. top - itr, sizeof(*assoc_request));
  187. break;
  188. }
  189. ar_type = le16_to_cpu(assoc_request->AssociationTypeId);
  190. ar_subtype = le16_to_cpu(assoc_request->AssociationSubTypeId);
  191. ar_size = le32_to_cpu(assoc_request->AssociationTypeInfoSize);
  192. switch (ar_type) {
  193. case AR_TYPE_WUSB:
  194. /* Verify we have what is mandated by AMS1.0 */
  195. switch (ar_subtype) {
  196. case AR_TYPE_WUSB_RETRIEVE_HOST_INFO:
  197. ar_name = "retrieve_host_info";
  198. ar_rhi_idx = ar_index;
  199. break;
  200. case AR_TYPE_WUSB_ASSOCIATE:
  201. /* send assoc data */
  202. ar_name = "associate";
  203. ar_assoc_idx = ar_index;
  204. break;
  205. default:
  206. ar_name = "unknown";
  207. };
  208. break;
  209. default:
  210. ar_name = "unknown";
  211. };
  212. d_printf(1, dev, "association request #%02u: 0x%04x/%04x "
  213. "(%zu bytes): %s\n",
  214. assoc_request->AssociationDataIndex, ar_type,
  215. ar_subtype, (size_t)ar_size, ar_name);
  216. itr += sizeof(*assoc_request);
  217. ar_index++;
  218. }
  219. if (ar_rhi_idx == -1) {
  220. dev_err(dev, "Missing RETRIEVE_HOST_INFO association "
  221. "request\n");
  222. goto error_bad_reqs;
  223. }
  224. if (ar_assoc_idx == -1) {
  225. dev_err(dev, "Missing ASSOCIATE association request\n");
  226. goto error_bad_reqs;
  227. }
  228. return 0;
  229. error_bad_header:
  230. error_bad_data:
  231. error_bad_reqs:
  232. error_get_assoc_types:
  233. return -EINVAL;
  234. }
  235. static const struct wusb_cbaf_host_info cbaf_host_info_defaults = {
  236. .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId,
  237. .AssociationTypeId = cpu_to_le16(AR_TYPE_WUSB),
  238. .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
  239. .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO),
  240. .CHID_hdr = WUSB_AR_CHID,
  241. .LangID_hdr = WUSB_AR_LangID,
  242. .HostFriendlyName_hdr = WUSB_AR_HostFriendlyName,
  243. };
  244. /* Send WUSB host information (CHID and name) to a CBAF device */
  245. static int cbaf_send_host_info(struct cbaf *cbaf)
  246. {
  247. struct wusb_cbaf_host_info *hi;
  248. size_t hi_size;
  249. hi = cbaf->buffer;
  250. memset(hi, 0, sizeof(*hi));
  251. *hi = cbaf_host_info_defaults;
  252. hi->CHID = cbaf->chid;
  253. hi->LangID = 0; /* FIXME: I guess... */
  254. strncpy(hi->HostFriendlyName, cbaf->host_name,
  255. hi->HostFriendlyName_hdr.len);
  256. hi->HostFriendlyName_hdr.len =
  257. cpu_to_le16(strlen(hi->HostFriendlyName));
  258. hi_size = sizeof(*hi) + strlen(hi->HostFriendlyName);
  259. return usb_control_msg(cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
  260. CBAF_REQ_SET_ASSOCIATION_RESPONSE,
  261. USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  262. 0x0101,
  263. cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
  264. hi, hi_size, 1000 /* FIXME: arbitrary */);
  265. }
  266. /* Show current CHID info we have set from user space */
  267. static ssize_t cbaf_wusb_host_info_show(struct device *dev,
  268. struct device_attribute *attr,
  269. char *buf)
  270. {
  271. struct usb_interface *iface = to_usb_interface(dev);
  272. struct cbaf *cbaf = usb_get_intfdata(iface);
  273. char pr_chid[WUSB_CKHDID_STRSIZE];
  274. ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid);
  275. return scnprintf(buf, PAGE_SIZE, "CHID: %s\nName: %s\n",
  276. pr_chid, cbaf->host_name);
  277. }
  278. /*
  279. * Get a host info CHID from user space and send it to the device.
  280. *
  281. * The user can recover a CC from the device associated to that CHID
  282. * by cat'ing wusb_connection_context.
  283. */
  284. static ssize_t cbaf_wusb_host_info_store(struct device *dev,
  285. struct device_attribute *attr,
  286. const char *buf, size_t size)
  287. {
  288. ssize_t result;
  289. struct usb_interface *iface = to_usb_interface(dev);
  290. struct cbaf *cbaf = usb_get_intfdata(iface);
  291. result = sscanf(buf,
  292. "%02hhx %02hhx %02hhx %02hhx "
  293. "%02hhx %02hhx %02hhx %02hhx "
  294. "%02hhx %02hhx %02hhx %02hhx "
  295. "%02hhx %02hhx %02hhx %02hhx "
  296. "%04hx %64s\n",
  297. &cbaf->chid.data[0] , &cbaf->chid.data[1],
  298. &cbaf->chid.data[2] , &cbaf->chid.data[3],
  299. &cbaf->chid.data[4] , &cbaf->chid.data[5],
  300. &cbaf->chid.data[6] , &cbaf->chid.data[7],
  301. &cbaf->chid.data[8] , &cbaf->chid.data[9],
  302. &cbaf->chid.data[10], &cbaf->chid.data[11],
  303. &cbaf->chid.data[12], &cbaf->chid.data[13],
  304. &cbaf->chid.data[14], &cbaf->chid.data[15],
  305. &cbaf->host_band_groups, cbaf->host_name);
  306. if (result != 18) {
  307. dev_err(dev, "Unrecognized CHID (need 16 8-bit hex digits, "
  308. "a 16 bit hex band group mask "
  309. "and a host name, got only %d)\n", (int)result);
  310. return -EINVAL;
  311. }
  312. result = cbaf_send_host_info(cbaf);
  313. if (result < 0)
  314. dev_err(dev, "Couldn't send host information to device: %d\n",
  315. (int)result);
  316. else
  317. d_printf(1, dev, "HI sent, wusb_cc can be read now\n");
  318. return result < 0 ? result : size;
  319. }
  320. static DEVICE_ATTR(wusb_host_info, 0600, cbaf_wusb_host_info_show,
  321. cbaf_wusb_host_info_store);
  322. static const struct wusb_cbaf_device_info cbaf_device_info_defaults = {
  323. .Length_hdr = WUSB_AR_Length,
  324. .CDID_hdr = WUSB_AR_CDID,
  325. .BandGroups_hdr = WUSB_AR_BandGroups,
  326. .LangID_hdr = WUSB_AR_LangID,
  327. .DeviceFriendlyName_hdr = WUSB_AR_DeviceFriendlyName,
  328. };
  329. /*
  330. * Get device's information (CDID) associated to CHID
  331. *
  332. * The device will return it's information (CDID, name, bandgroups)
  333. * associated to the CHID we have set before, or 0 CDID and default
  334. * name and bandgroup if no CHID set or unknown.
  335. */
  336. static int cbaf_cdid_get(struct cbaf *cbaf)
  337. {
  338. int result;
  339. struct device *dev = &cbaf->usb_iface->dev;
  340. struct wusb_cbaf_device_info *di;
  341. size_t needed, dev_name_size;
  342. di = cbaf->buffer;
  343. result = usb_control_msg(
  344. cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
  345. CBAF_REQ_GET_ASSOCIATION_REQUEST,
  346. USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  347. 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
  348. di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
  349. if (result < 0) {
  350. dev_err(dev, "Cannot request device information: %d\n", result);
  351. goto error_req_di;
  352. }
  353. needed = result < sizeof(*di) ? sizeof(*di) : le32_to_cpu(di->Length);
  354. if (result < needed) {
  355. dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
  356. "%zu bytes needed)\n", (size_t)result, needed);
  357. goto error_bad_di;
  358. }
  359. cbaf->cdid = di->CDID;
  360. dev_name_size = le16_to_cpu(di->DeviceFriendlyName_hdr.len);
  361. dev_name_size = dev_name_size > 65 - 1 ? 65 - 1 : dev_name_size;
  362. memcpy(cbaf->device_name, di->DeviceFriendlyName, dev_name_size);
  363. cbaf->device_name[dev_name_size] = 0;
  364. cbaf->device_band_groups = le16_to_cpu(di->BandGroups);
  365. result = 0;
  366. error_req_di:
  367. error_bad_di:
  368. return result;
  369. }
  370. /*
  371. * Get device information and print it to sysfs
  372. *
  373. * See cbaf_cdid_get()
  374. */
  375. static ssize_t cbaf_wusb_cdid_show(struct device *dev,
  376. struct device_attribute *attr, char *buf)
  377. {
  378. ssize_t result;
  379. struct usb_interface *iface = to_usb_interface(dev);
  380. struct cbaf *cbaf = usb_get_intfdata(iface);
  381. char pr_cdid[WUSB_CKHDID_STRSIZE];
  382. result = cbaf_cdid_get(cbaf);
  383. if (result < 0) {
  384. dev_err(dev, "Cannot read device information: %d\n",
  385. (int)result);
  386. goto error_get_di;
  387. }
  388. ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid);
  389. result = scnprintf(buf, PAGE_SIZE,
  390. "CDID: %s\nName: %s\nBand_groups: 0x%04x\n",
  391. pr_cdid, cbaf->device_name,
  392. cbaf->device_band_groups);
  393. error_get_di:
  394. return result;
  395. }
  396. static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, NULL);
  397. static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = {
  398. .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId,
  399. .AssociationTypeId = cpu_to_le16(AR_TYPE_WUSB),
  400. .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
  401. .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE),
  402. .Length_hdr = WUSB_AR_Length,
  403. .Length = cpu_to_le32(sizeof(struct wusb_cbaf_cc_data)),
  404. .ConnectionContext_hdr = WUSB_AR_ConnectionContext,
  405. .BandGroups_hdr = WUSB_AR_BandGroups,
  406. };
  407. static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults = {
  408. .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId,
  409. .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
  410. .Length_hdr = WUSB_AR_Length,
  411. .AssociationStatus_hdr = WUSB_AR_AssociationStatus,
  412. };
  413. /*
  414. * Send a new CC to the device
  415. *
  416. * So we update the CK and send the whole thing to the device
  417. */
  418. static int cbaf_cc_upload(struct cbaf *cbaf)
  419. {
  420. int result;
  421. struct device *dev = &cbaf->usb_iface->dev;
  422. struct wusb_cbaf_cc_data *ccd;
  423. char pr_cdid[WUSB_CKHDID_STRSIZE];
  424. ccd = cbaf->buffer;
  425. *ccd = cbaf_cc_data_defaults;
  426. ccd->CHID = cbaf->chid;
  427. ccd->CDID = cbaf->cdid;
  428. ccd->CK = cbaf->ck;
  429. ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups);
  430. result = usb_control_msg(
  431. cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
  432. CBAF_REQ_SET_ASSOCIATION_RESPONSE,
  433. USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  434. 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
  435. ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */);
  436. d_printf(1, dev, "Uploaded CC:\n");
  437. ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID);
  438. d_printf(1, dev, " CHID %s\n", pr_cdid);
  439. ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID);
  440. d_printf(1, dev, " CDID %s\n", pr_cdid);
  441. ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CK);
  442. d_printf(1, dev, " CK %s\n", pr_cdid);
  443. d_printf(1, dev, " bandgroups 0x%04x\n", cbaf->host_band_groups);
  444. return result;
  445. }
  446. /*
  447. * Send a new CC to the device
  448. *
  449. * We take the CDID and CK from user space, the rest from the info we
  450. * set with host_info.
  451. */
  452. static ssize_t cbaf_wusb_cc_store(struct device *dev,
  453. struct device_attribute *attr,
  454. const char *buf, size_t size)
  455. {
  456. ssize_t result;
  457. struct usb_interface *iface = to_usb_interface(dev);
  458. struct cbaf *cbaf = usb_get_intfdata(iface);
  459. result = sscanf(buf,
  460. "CDID: %02hhx %02hhx %02hhx %02hhx "
  461. "%02hhx %02hhx %02hhx %02hhx "
  462. "%02hhx %02hhx %02hhx %02hhx "
  463. "%02hhx %02hhx %02hhx %02hhx\n"
  464. "CK: %02hhx %02hhx %02hhx %02hhx "
  465. "%02hhx %02hhx %02hhx %02hhx "
  466. "%02hhx %02hhx %02hhx %02hhx "
  467. "%02hhx %02hhx %02hhx %02hhx\n",
  468. &cbaf->cdid.data[0] , &cbaf->cdid.data[1],
  469. &cbaf->cdid.data[2] , &cbaf->cdid.data[3],
  470. &cbaf->cdid.data[4] , &cbaf->cdid.data[5],
  471. &cbaf->cdid.data[6] , &cbaf->cdid.data[7],
  472. &cbaf->cdid.data[8] , &cbaf->cdid.data[9],
  473. &cbaf->cdid.data[10], &cbaf->cdid.data[11],
  474. &cbaf->cdid.data[12], &cbaf->cdid.data[13],
  475. &cbaf->cdid.data[14], &cbaf->cdid.data[15],
  476. &cbaf->ck.data[0] , &cbaf->ck.data[1],
  477. &cbaf->ck.data[2] , &cbaf->ck.data[3],
  478. &cbaf->ck.data[4] , &cbaf->ck.data[5],
  479. &cbaf->ck.data[6] , &cbaf->ck.data[7],
  480. &cbaf->ck.data[8] , &cbaf->ck.data[9],
  481. &cbaf->ck.data[10], &cbaf->ck.data[11],
  482. &cbaf->ck.data[12], &cbaf->ck.data[13],
  483. &cbaf->ck.data[14], &cbaf->ck.data[15]);
  484. if (result != 32) {
  485. dev_err(dev, "Unrecognized CHID/CK (need 32 8-bit "
  486. "hex digits, got only %d)\n", (int)result);
  487. return -EINVAL;
  488. }
  489. result = cbaf_cc_upload(cbaf);
  490. if (result < 0)
  491. dev_err(dev, "Couldn't upload connection context: %d\n",
  492. (int)result);
  493. else
  494. d_printf(1, dev, "Connection context uploaded\n");
  495. return result < 0 ? result : size;
  496. }
  497. static DEVICE_ATTR(wusb_cc, 0600, NULL, cbaf_wusb_cc_store);
  498. static struct attribute *cbaf_dev_attrs[] = {
  499. &dev_attr_wusb_host_info.attr,
  500. &dev_attr_wusb_cdid.attr,
  501. &dev_attr_wusb_cc.attr,
  502. NULL,
  503. };
  504. static struct attribute_group cbaf_dev_attr_group = {
  505. .name = NULL, /* we want them in the same directory */
  506. .attrs = cbaf_dev_attrs,
  507. };
  508. static int cbaf_probe(struct usb_interface *iface,
  509. const struct usb_device_id *id)
  510. {
  511. int result;
  512. struct cbaf *cbaf;
  513. struct device *dev = &iface->dev;
  514. result = -ENOMEM;
  515. cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL);
  516. if (cbaf == NULL) {
  517. dev_err(dev, "Unable to allocate instance\n");
  518. goto error_kzalloc;
  519. }
  520. cbaf->buffer = kmalloc(512, GFP_KERNEL);
  521. if (cbaf->buffer == NULL)
  522. goto error_kmalloc_buffer;
  523. cbaf->buffer_size = 512;
  524. cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface));
  525. cbaf->usb_iface = usb_get_intf(iface);
  526. result = cbaf_check(cbaf);
  527. if (result < 0)
  528. goto error_check;
  529. result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group);
  530. if (result < 0) {
  531. dev_err(dev, "Can't register sysfs attr group: %d\n", result);
  532. goto error_create_group;
  533. }
  534. usb_set_intfdata(iface, cbaf);
  535. d_printf(2, dev, "CBA attached\n");
  536. return 0;
  537. error_create_group:
  538. error_check:
  539. kfree(cbaf->buffer);
  540. error_kmalloc_buffer:
  541. kfree(cbaf);
  542. error_kzalloc:
  543. return result;
  544. }
  545. static void cbaf_disconnect(struct usb_interface *iface)
  546. {
  547. struct cbaf *cbaf = usb_get_intfdata(iface);
  548. struct device *dev = &iface->dev;
  549. sysfs_remove_group(&dev->kobj, &cbaf_dev_attr_group);
  550. usb_set_intfdata(iface, NULL);
  551. usb_put_intf(iface);
  552. kfree(cbaf->buffer);
  553. /* paranoia: clean up crypto keys */
  554. memset(cbaf, 0, sizeof(*cbaf));
  555. kfree(cbaf);
  556. d_printf(1, dev, "CBA detached\n");
  557. }
  558. static struct usb_device_id cbaf_id_table[] = {
  559. { USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
  560. { },
  561. };
  562. MODULE_DEVICE_TABLE(usb, cbaf_id_table);
  563. static struct usb_driver cbaf_driver = {
  564. .name = "wusb-cbaf",
  565. .id_table = cbaf_id_table,
  566. .probe = cbaf_probe,
  567. .disconnect = cbaf_disconnect,
  568. };
  569. static int __init cbaf_driver_init(void)
  570. {
  571. return usb_register(&cbaf_driver);
  572. }
  573. module_init(cbaf_driver_init);
  574. static void __exit cbaf_driver_exit(void)
  575. {
  576. usb_deregister(&cbaf_driver);
  577. }
  578. module_exit(cbaf_driver_exit);
  579. MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
  580. MODULE_DESCRIPTION("Wireless USB Cable Based Association");
  581. MODULE_LICENSE("GPL");