usb.c 10 KB

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