bcm203x.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * Broadcom Blutonium firmware driver
  5. *
  6. * Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
  7. * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/atomic.h>
  11. #include <linux/kernel.h>
  12. #include <linux/init.h>
  13. #include <linux/slab.h>
  14. #include <linux/types.h>
  15. #include <linux/errno.h>
  16. #include <linux/device.h>
  17. #include <linux/firmware.h>
  18. #include <linux/usb.h>
  19. #include <net/bluetooth/bluetooth.h>
  20. #define VERSION "1.2"
  21. static const struct usb_device_id bcm203x_table[] = {
  22. /* Broadcom Blutonium (BCM2033) */
  23. { USB_DEVICE(0x0a5c, 0x2033) },
  24. { } /* Terminating entry */
  25. };
  26. MODULE_DEVICE_TABLE(usb, bcm203x_table);
  27. #define BCM203X_ERROR 0
  28. #define BCM203X_RESET 1
  29. #define BCM203X_LOAD_MINIDRV 2
  30. #define BCM203X_SELECT_MEMORY 3
  31. #define BCM203X_CHECK_MEMORY 4
  32. #define BCM203X_LOAD_FIRMWARE 5
  33. #define BCM203X_CHECK_FIRMWARE 6
  34. #define BCM203X_IN_EP 0x81
  35. #define BCM203X_OUT_EP 0x02
  36. struct bcm203x_data {
  37. struct usb_device *udev;
  38. unsigned long state;
  39. struct work_struct work;
  40. atomic_t shutdown;
  41. struct urb *urb;
  42. unsigned char *buffer;
  43. unsigned char *fw_data;
  44. unsigned int fw_size;
  45. unsigned int fw_sent;
  46. };
  47. static void bcm203x_complete(struct urb *urb)
  48. {
  49. struct bcm203x_data *data = urb->context;
  50. struct usb_device *udev = urb->dev;
  51. int len;
  52. BT_DBG("udev %p urb %p", udev, urb);
  53. if (urb->status) {
  54. BT_ERR("URB failed with status %d", urb->status);
  55. data->state = BCM203X_ERROR;
  56. return;
  57. }
  58. switch (data->state) {
  59. case BCM203X_LOAD_MINIDRV:
  60. memcpy(data->buffer, "#", 1);
  61. usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
  62. data->buffer, 1, bcm203x_complete, data);
  63. data->state = BCM203X_SELECT_MEMORY;
  64. /* use workqueue to have a small delay */
  65. schedule_work(&data->work);
  66. break;
  67. case BCM203X_SELECT_MEMORY:
  68. usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
  69. data->buffer, 32, bcm203x_complete, data, 1);
  70. data->state = BCM203X_CHECK_MEMORY;
  71. if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
  72. BT_ERR("Can't submit URB");
  73. break;
  74. case BCM203X_CHECK_MEMORY:
  75. if (data->buffer[0] != '#') {
  76. BT_ERR("Memory select failed");
  77. data->state = BCM203X_ERROR;
  78. break;
  79. }
  80. data->state = BCM203X_LOAD_FIRMWARE;
  81. fallthrough;
  82. case BCM203X_LOAD_FIRMWARE:
  83. if (data->fw_sent == data->fw_size) {
  84. usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
  85. data->buffer, 32, bcm203x_complete, data, 1);
  86. data->state = BCM203X_CHECK_FIRMWARE;
  87. } else {
  88. len = min_t(uint, data->fw_size - data->fw_sent, 4096);
  89. usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
  90. data->fw_data + data->fw_sent, len, bcm203x_complete, data);
  91. data->fw_sent += len;
  92. }
  93. if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
  94. BT_ERR("Can't submit URB");
  95. break;
  96. case BCM203X_CHECK_FIRMWARE:
  97. if (data->buffer[0] != '.') {
  98. BT_ERR("Firmware loading failed");
  99. data->state = BCM203X_ERROR;
  100. break;
  101. }
  102. data->state = BCM203X_RESET;
  103. break;
  104. }
  105. }
  106. static void bcm203x_work(struct work_struct *work)
  107. {
  108. struct bcm203x_data *data =
  109. container_of(work, struct bcm203x_data, work);
  110. if (atomic_read(&data->shutdown))
  111. return;
  112. if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)
  113. BT_ERR("Can't submit URB");
  114. }
  115. static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id)
  116. {
  117. const struct firmware *firmware;
  118. struct usb_device *udev = interface_to_usbdev(intf);
  119. struct bcm203x_data *data;
  120. int size;
  121. BT_DBG("intf %p id %p", intf, id);
  122. if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
  123. return -ENODEV;
  124. data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
  125. if (!data)
  126. return -ENOMEM;
  127. data->udev = udev;
  128. data->state = BCM203X_LOAD_MINIDRV;
  129. data->urb = usb_alloc_urb(0, GFP_KERNEL);
  130. if (!data->urb)
  131. return -ENOMEM;
  132. if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
  133. BT_ERR("Mini driver request failed");
  134. usb_free_urb(data->urb);
  135. return -EIO;
  136. }
  137. BT_DBG("minidrv data %p size %zu", firmware->data, firmware->size);
  138. size = max_t(uint, firmware->size, 4096);
  139. data->buffer = kmalloc(size, GFP_KERNEL);
  140. if (!data->buffer) {
  141. BT_ERR("Can't allocate memory for mini driver");
  142. release_firmware(firmware);
  143. usb_free_urb(data->urb);
  144. return -ENOMEM;
  145. }
  146. memcpy(data->buffer, firmware->data, firmware->size);
  147. usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
  148. data->buffer, firmware->size, bcm203x_complete, data);
  149. release_firmware(firmware);
  150. if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) {
  151. BT_ERR("Firmware request failed");
  152. usb_free_urb(data->urb);
  153. kfree(data->buffer);
  154. return -EIO;
  155. }
  156. BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
  157. data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
  158. if (!data->fw_data) {
  159. BT_ERR("Can't allocate memory for firmware image");
  160. release_firmware(firmware);
  161. usb_free_urb(data->urb);
  162. kfree(data->buffer);
  163. return -ENOMEM;
  164. }
  165. data->fw_size = firmware->size;
  166. data->fw_sent = 0;
  167. release_firmware(firmware);
  168. INIT_WORK(&data->work, bcm203x_work);
  169. usb_set_intfdata(intf, data);
  170. /* use workqueue to have a small delay */
  171. schedule_work(&data->work);
  172. return 0;
  173. }
  174. static void bcm203x_disconnect(struct usb_interface *intf)
  175. {
  176. struct bcm203x_data *data = usb_get_intfdata(intf);
  177. BT_DBG("intf %p", intf);
  178. atomic_inc(&data->shutdown);
  179. cancel_work_sync(&data->work);
  180. usb_kill_urb(data->urb);
  181. usb_set_intfdata(intf, NULL);
  182. usb_free_urb(data->urb);
  183. kfree(data->fw_data);
  184. kfree(data->buffer);
  185. }
  186. static struct usb_driver bcm203x_driver = {
  187. .name = "bcm203x",
  188. .probe = bcm203x_probe,
  189. .disconnect = bcm203x_disconnect,
  190. .id_table = bcm203x_table,
  191. .disable_hub_initiated_lpm = 1,
  192. };
  193. module_usb_driver(bcm203x_driver);
  194. MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
  195. MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
  196. MODULE_VERSION(VERSION);
  197. MODULE_LICENSE("GPL");
  198. MODULE_FIRMWARE("BCM2033-MD.hex");
  199. MODULE_FIRMWARE("BCM2033-FW.bin");