usb.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * Copyright (c) 2007-2011 Atheros Communications Inc.
  3. * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/usb.h>
  19. #include "debug.h"
  20. #include "core.h"
  21. /* usb device object */
  22. struct ath6kl_usb {
  23. struct usb_device *udev;
  24. struct usb_interface *interface;
  25. u8 *diag_cmd_buffer;
  26. u8 *diag_resp_buffer;
  27. struct ath6kl *ar;
  28. };
  29. /* diagnostic command defnitions */
  30. #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1
  31. #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2
  32. #define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3
  33. #define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4
  34. #define ATH6KL_USB_CTRL_DIAG_CC_READ 0
  35. #define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1
  36. struct ath6kl_usb_ctrl_diag_cmd_write {
  37. __le32 cmd;
  38. __le32 address;
  39. __le32 value;
  40. __le32 _pad[1];
  41. } __packed;
  42. struct ath6kl_usb_ctrl_diag_cmd_read {
  43. __le32 cmd;
  44. __le32 address;
  45. } __packed;
  46. struct ath6kl_usb_ctrl_diag_resp_read {
  47. __le32 value;
  48. } __packed;
  49. #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write))
  50. #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read))
  51. static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb)
  52. {
  53. usb_set_intfdata(ar_usb->interface, NULL);
  54. kfree(ar_usb->diag_cmd_buffer);
  55. kfree(ar_usb->diag_resp_buffer);
  56. kfree(ar_usb);
  57. }
  58. static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface)
  59. {
  60. struct ath6kl_usb *ar_usb = NULL;
  61. struct usb_device *dev = interface_to_usbdev(interface);
  62. int status = 0;
  63. ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL);
  64. if (ar_usb == NULL)
  65. goto fail_ath6kl_usb_create;
  66. memset(ar_usb, 0, sizeof(struct ath6kl_usb));
  67. usb_set_intfdata(interface, ar_usb);
  68. ar_usb->udev = dev;
  69. ar_usb->interface = interface;
  70. ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL);
  71. if (ar_usb->diag_cmd_buffer == NULL) {
  72. status = -ENOMEM;
  73. goto fail_ath6kl_usb_create;
  74. }
  75. ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP,
  76. GFP_KERNEL);
  77. if (ar_usb->diag_resp_buffer == NULL) {
  78. status = -ENOMEM;
  79. goto fail_ath6kl_usb_create;
  80. }
  81. fail_ath6kl_usb_create:
  82. if (status != 0) {
  83. ath6kl_usb_destroy(ar_usb);
  84. ar_usb = NULL;
  85. }
  86. return ar_usb;
  87. }
  88. static void ath6kl_usb_device_detached(struct usb_interface *interface)
  89. {
  90. struct ath6kl_usb *ar_usb;
  91. ar_usb = usb_get_intfdata(interface);
  92. if (ar_usb == NULL)
  93. return;
  94. ath6kl_stop_txrx(ar_usb->ar);
  95. ath6kl_core_cleanup(ar_usb->ar);
  96. ath6kl_usb_destroy(ar_usb);
  97. }
  98. static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb,
  99. u8 req, u16 value, u16 index, void *data,
  100. u32 size)
  101. {
  102. u8 *buf = NULL;
  103. int ret;
  104. if (size > 0) {
  105. buf = kmalloc(size, GFP_KERNEL);
  106. if (buf == NULL)
  107. return -ENOMEM;
  108. memcpy(buf, data, size);
  109. }
  110. /* note: if successful returns number of bytes transfered */
  111. ret = usb_control_msg(ar_usb->udev,
  112. usb_sndctrlpipe(ar_usb->udev, 0),
  113. req,
  114. USB_DIR_OUT | USB_TYPE_VENDOR |
  115. USB_RECIP_DEVICE, value, index, buf,
  116. size, 1000);
  117. if (ret < 0) {
  118. ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
  119. __func__, ret);
  120. }
  121. kfree(buf);
  122. return 0;
  123. }
  124. static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb,
  125. u8 req, u16 value, u16 index, void *data,
  126. u32 size)
  127. {
  128. u8 *buf = NULL;
  129. int ret;
  130. if (size > 0) {
  131. buf = kmalloc(size, GFP_KERNEL);
  132. if (buf == NULL)
  133. return -ENOMEM;
  134. }
  135. /* note: if successful returns number of bytes transfered */
  136. ret = usb_control_msg(ar_usb->udev,
  137. usb_rcvctrlpipe(ar_usb->udev, 0),
  138. req,
  139. USB_DIR_IN | USB_TYPE_VENDOR |
  140. USB_RECIP_DEVICE, value, index, buf,
  141. size, 2 * HZ);
  142. if (ret < 0) {
  143. ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n",
  144. __func__, ret);
  145. }
  146. memcpy((u8 *) data, buf, size);
  147. kfree(buf);
  148. return 0;
  149. }
  150. static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb,
  151. u8 req_val, u8 *req_buf, u32 req_len,
  152. u8 resp_val, u8 *resp_buf, u32 *resp_len)
  153. {
  154. int ret;
  155. /* send command */
  156. ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0,
  157. req_buf, req_len);
  158. if (ret != 0)
  159. return ret;
  160. if (resp_buf == NULL) {
  161. /* no expected response */
  162. return ret;
  163. }
  164. /* get response */
  165. ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0,
  166. resp_buf, *resp_len);
  167. return ret;
  168. }
  169. static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
  170. {
  171. struct ath6kl_usb *ar_usb = ar->hif_priv;
  172. struct ath6kl_usb_ctrl_diag_resp_read *resp;
  173. struct ath6kl_usb_ctrl_diag_cmd_read *cmd;
  174. u32 resp_len;
  175. int ret;
  176. cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer;
  177. memset(cmd, 0, sizeof(*cmd));
  178. cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ;
  179. cmd->address = cpu_to_le32(address);
  180. resp_len = sizeof(*resp);
  181. ret = ath6kl_usb_ctrl_msg_exchange(ar_usb,
  182. ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
  183. (u8 *) cmd,
  184. sizeof(struct ath6kl_usb_ctrl_diag_cmd_write),
  185. ATH6KL_USB_CONTROL_REQ_DIAG_RESP,
  186. ar_usb->diag_resp_buffer, &resp_len);
  187. if (ret)
  188. return ret;
  189. resp = (struct ath6kl_usb_ctrl_diag_resp_read *)
  190. ar_usb->diag_resp_buffer;
  191. *data = le32_to_cpu(resp->value);
  192. return ret;
  193. }
  194. static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data)
  195. {
  196. struct ath6kl_usb *ar_usb = ar->hif_priv;
  197. struct ath6kl_usb_ctrl_diag_cmd_write *cmd;
  198. cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer;
  199. memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write));
  200. cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE);
  201. cmd->address = cpu_to_le32(address);
  202. cmd->value = data;
  203. return ath6kl_usb_ctrl_msg_exchange(ar_usb,
  204. ATH6KL_USB_CONTROL_REQ_DIAG_CMD,
  205. (u8 *) cmd,
  206. sizeof(*cmd),
  207. 0, NULL, NULL);
  208. }
  209. static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len)
  210. {
  211. struct ath6kl_usb *ar_usb = ar->hif_priv;
  212. int ret;
  213. /* get response */
  214. ret = ath6kl_usb_submit_ctrl_in(ar_usb,
  215. ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP,
  216. 0, 0, buf, len);
  217. if (ret != 0) {
  218. ath6kl_err("Unable to read the bmi data from the device: %d\n",
  219. ret);
  220. return ret;
  221. }
  222. return 0;
  223. }
  224. static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len)
  225. {
  226. struct ath6kl_usb *ar_usb = ar->hif_priv;
  227. int ret;
  228. /* send command */
  229. ret = ath6kl_usb_submit_ctrl_out(ar_usb,
  230. ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD,
  231. 0, 0, buf, len);
  232. if (ret != 0) {
  233. ath6kl_err("unable to send the bmi data to the device: %d\n",
  234. ret);
  235. return ret;
  236. }
  237. return 0;
  238. }
  239. static int ath6kl_usb_power_on(struct ath6kl *ar)
  240. {
  241. return 0;
  242. }
  243. static int ath6kl_usb_power_off(struct ath6kl *ar)
  244. {
  245. return 0;
  246. }
  247. static const struct ath6kl_hif_ops ath6kl_usb_ops = {
  248. .diag_read32 = ath6kl_usb_diag_read32,
  249. .diag_write32 = ath6kl_usb_diag_write32,
  250. .bmi_read = ath6kl_usb_bmi_read,
  251. .bmi_write = ath6kl_usb_bmi_write,
  252. .power_on = ath6kl_usb_power_on,
  253. .power_off = ath6kl_usb_power_off,
  254. };
  255. /* ath6kl usb driver registered functions */
  256. static int ath6kl_usb_probe(struct usb_interface *interface,
  257. const struct usb_device_id *id)
  258. {
  259. struct usb_device *dev = interface_to_usbdev(interface);
  260. struct ath6kl *ar;
  261. struct ath6kl_usb *ar_usb = NULL;
  262. int vendor_id, product_id;
  263. int ret = 0;
  264. usb_get_dev(dev);
  265. vendor_id = le16_to_cpu(dev->descriptor.idVendor);
  266. product_id = le16_to_cpu(dev->descriptor.idProduct);
  267. ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id);
  268. ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id);
  269. if (interface->cur_altsetting)
  270. ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n",
  271. interface->cur_altsetting->desc.bInterfaceNumber);
  272. if (dev->speed == USB_SPEED_HIGH)
  273. ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n");
  274. else
  275. ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n");
  276. ar_usb = ath6kl_usb_create(interface);
  277. if (ar_usb == NULL) {
  278. ret = -ENOMEM;
  279. goto err_usb_put;
  280. }
  281. ar = ath6kl_core_create(&ar_usb->udev->dev);
  282. if (ar == NULL) {
  283. ath6kl_err("Failed to alloc ath6kl core\n");
  284. ret = -ENOMEM;
  285. goto err_usb_destroy;
  286. }
  287. ar->hif_priv = ar_usb;
  288. ar->hif_type = ATH6KL_HIF_TYPE_USB;
  289. ar->hif_ops = &ath6kl_usb_ops;
  290. ar->mbox_info.block_size = 16;
  291. ar->bmi.max_data_size = 252;
  292. ar_usb->ar = ar;
  293. ret = ath6kl_core_init(ar);
  294. if (ret) {
  295. ath6kl_err("Failed to init ath6kl core: %d\n", ret);
  296. goto err_core_free;
  297. }
  298. return ret;
  299. err_core_free:
  300. ath6kl_core_destroy(ar);
  301. err_usb_destroy:
  302. ath6kl_usb_destroy(ar_usb);
  303. err_usb_put:
  304. usb_put_dev(dev);
  305. return ret;
  306. }
  307. static void ath6kl_usb_remove(struct usb_interface *interface)
  308. {
  309. usb_put_dev(interface_to_usbdev(interface));
  310. ath6kl_usb_device_detached(interface);
  311. }
  312. /* table of devices that work with this driver */
  313. static struct usb_device_id ath6kl_usb_ids[] = {
  314. {USB_DEVICE(0x0cf3, 0x9374)},
  315. { /* Terminating entry */ },
  316. };
  317. MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids);
  318. static struct usb_driver ath6kl_usb_driver = {
  319. .name = "ath6kl_usb",
  320. .probe = ath6kl_usb_probe,
  321. .disconnect = ath6kl_usb_remove,
  322. .id_table = ath6kl_usb_ids,
  323. };
  324. static int ath6kl_usb_init(void)
  325. {
  326. usb_register(&ath6kl_usb_driver);
  327. return 0;
  328. }
  329. static void ath6kl_usb_exit(void)
  330. {
  331. usb_deregister(&ath6kl_usb_driver);
  332. }
  333. module_init(ath6kl_usb_init);
  334. module_exit(ath6kl_usb_exit);
  335. MODULE_AUTHOR("Atheros Communications, Inc.");
  336. MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices");
  337. MODULE_LICENSE("Dual BSD/GPL");
  338. MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE);
  339. MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE);
  340. MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);
  341. MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE);
  342. MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);
  343. MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);