├── LICENSE ├── Makefile ├── adapter.h ├── esp.h ├── esp_api.h ├── esp_bt.c ├── esp_bt_api.h ├── esp_if.h ├── esp_rb.c ├── esp_rb.h ├── esp_serial.c ├── esp_serial.h ├── main.c ├── sdio ├── esp_sdio.c ├── esp_sdio_api.c ├── esp_sdio_api.h └── esp_sdio_decl.h └── spi ├── esp_spi.c └── esp_spi.h /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build 2 | 3 | CONFIG_SUPPORT_ESP_SERIAL ?= y 4 | CONFIG_ENABLE_MONITOR_PROCESS ?= n 5 | 6 | # Default interface is SPI 7 | target ?= spi 8 | 9 | # Targets passed overrrides default value 10 | ifeq ($(target), sdio) 11 | MODULE_NAME=esp32_sdio 12 | endif 13 | ifeq ($(target), spi) 14 | MODULE_NAME=esp32_spi 15 | endif 16 | 17 | ifeq ($(CONFIG_SUPPORT_ESP_SERIAL), y) 18 | EXTRA_CFLAGS += -DCONFIG_SUPPORT_ESP_SERIAL 19 | endif 20 | 21 | ifeq ($(CONFIG_ENABLE_MONITOR_PROCESS), y) 22 | EXTRA_CFLAGS += -DCONFIG_ENABLE_MONITOR_PROCESS 23 | endif 24 | 25 | EXTRA_CFLAGS += -I$(PWD) 26 | 27 | ifeq ($(MODULE_NAME), esp32_sdio) 28 | module_objects += sdio/esp_sdio.o sdio/esp_sdio_api.o 29 | endif 30 | 31 | ifeq ($(MODULE_NAME), esp32_spi) 32 | module_objects += spi/esp_spi.o 33 | endif 34 | 35 | obj-m := $(MODULE_NAME).o 36 | $(MODULE_NAME)-y := esp_bt.o main.o $(module_objects) 37 | 38 | ifeq ($(CONFIG_SUPPORT_ESP_SERIAL), y) 39 | $(MODULE_NAME)-y += esp_serial.o esp_rb.o 40 | endif 41 | 42 | all: 43 | $(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) modules $(KBUILD_OPTIONS) 44 | 45 | modules_install: 46 | $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(CURDIR) modules_install 47 | 48 | clean: 49 | $(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) clean 50 | -------------------------------------------------------------------------------- /adapter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD 2 | /* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */ 3 | 4 | #ifndef __ESP_NETWORK_ADAPTER__H 5 | #define __ESP_NETWORK_ADAPTER__H 6 | 7 | struct esp_payload_header { 8 | uint8_t if_type:4; 9 | uint8_t if_num:4; 10 | uint8_t reserved1; 11 | uint16_t len; 12 | uint16_t offset; 13 | uint8_t reserved2; 14 | union { 15 | uint8_t reserved3; 16 | uint8_t hci_pkt_type; /* Packet type for HCI interface */ 17 | uint8_t priv_pkt_type; /* Packet type for priv interface */ 18 | }; 19 | } __attribute__((packed)); 20 | 21 | typedef enum { 22 | ESP_STA_IF, 23 | ESP_AP_IF, 24 | ESP_SERIAL_IF, 25 | ESP_HCI_IF, 26 | ESP_PRIV_IF, 27 | } ESP_INTERFACE_TYPE; 28 | 29 | typedef enum { 30 | ESP_OPEN_DATA_PATH, 31 | ESP_CLOSE_DATA_PATH, 32 | ESP_RESET, 33 | } ESP_HOST_INTERRUPT; 34 | 35 | 36 | typedef enum { 37 | ESP_WLAN_SDIO_SUPPORT = (1 << 0), 38 | ESP_BT_UART_SUPPORT = (1 << 1), 39 | ESP_BT_SDIO_SUPPORT = (1 << 2), 40 | ESP_BLE_ONLY_SUPPORT = (1 << 3), 41 | ESP_BR_EDR_ONLY_SUPPORT = (1 << 4), 42 | ESP_WLAN_SPI_SUPPORT = (1 << 5), 43 | ESP_BT_SPI_SUPPORT = (1 << 6), 44 | } ESP_CAPABILITIES; 45 | 46 | typedef enum { 47 | ESP_PACKET_TYPE_EVENT, 48 | } ESP_PRIV_PACKET_TYPE; 49 | 50 | typedef enum { 51 | ESP_PRIV_EVENT_INIT, 52 | } ESP_PRIV_EVENT_TYPE; 53 | 54 | typedef enum { 55 | ESP_PRIV_CAPABILITY, 56 | } ESP_PRIV_TAG_TYPE; 57 | 58 | struct esp_priv_event { 59 | uint8_t event_type; 60 | uint8_t event_len; 61 | uint8_t event_data[0]; 62 | }__attribute__((packed)); 63 | #endif 64 | -------------------------------------------------------------------------------- /esp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef __esp__h_ 21 | #define __esp__h_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "adapter.h" 29 | 30 | #define ESP_IF_TYPE_SDIO 1 31 | #define ESP_IF_TYPE_SPI 2 32 | 33 | /* Network link status */ 34 | #define ESP_LINK_DOWN 0 35 | #define ESP_LINK_UP 1 36 | 37 | #define ESP_MAX_INTERFACE 2 38 | 39 | #define ESP_PAYLOAD_HEADER 8 40 | struct esp_private; 41 | struct esp_adapter; 42 | 43 | #define ACQUIRE_LOCK 1 44 | #define LOCK_ALREADY_ACQUIRED 0 45 | 46 | struct esp_adapter { 47 | u8 if_type; 48 | u32 capabilities; 49 | 50 | /* Possible types: 51 | * struct esp_sdio_context */ 52 | void *if_context; 53 | 54 | struct esp_if_ops *if_ops; 55 | 56 | /* Private for each interface */ 57 | struct esp_private *priv[ESP_MAX_INTERFACE]; 58 | struct hci_dev *hcidev; 59 | 60 | struct workqueue_struct *if_rx_workqueue; 61 | struct work_struct if_rx_work; 62 | 63 | /* Process TX work */ 64 | struct workqueue_struct *tx_workqueue; 65 | struct work_struct tx_work; 66 | 67 | /* TX queue */ 68 | struct sk_buff_head tx_q; 69 | 70 | /* RX Queue */ 71 | struct sk_buff_head rx_q; 72 | 73 | /* Counters */ 74 | atomic_t tx_pending; 75 | atomic_t rx_pending; 76 | }; 77 | 78 | 79 | struct esp_private { 80 | struct esp_adapter *adapter; 81 | struct net_device *ndev; 82 | struct net_device_stats stats; 83 | u8 link_state; 84 | u8 mac_address[6]; 85 | u8 if_type; 86 | u8 if_num; 87 | }; 88 | 89 | struct esp_skb_cb { 90 | struct esp_private *priv; 91 | }; 92 | 93 | void deinit_adapter(void); 94 | void esp_reset(void); 95 | struct esp_adapter * init_adapter(void); 96 | #endif 97 | -------------------------------------------------------------------------------- /esp_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef _esp_api__h_ 21 | #define _esp_api__h_ 22 | 23 | #include "esp.h" 24 | 25 | int esp_add_card(struct esp_adapter *adapter); 26 | int esp_remove_card(struct esp_adapter *adapter); 27 | void esp_process_new_packet_intr(struct esp_adapter *adapter); 28 | struct esp_adapter * esp_get_adapter(void); 29 | struct sk_buff * esp_alloc_skb(u32 len); 30 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size); 31 | u8 esp_is_bt_supported_over_sdio(u32 cap); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /esp_bt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | #include "esp_bt_api.h" 20 | #include "esp_api.h" 21 | 22 | void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len) 23 | { 24 | if (hdev) { 25 | if (pkt_type == HCI_COMMAND_PKT) { 26 | hdev->stat.cmd_tx++; 27 | } else if (pkt_type == HCI_ACLDATA_PKT) { 28 | hdev->stat.acl_tx++; 29 | } else if (pkt_type == HCI_SCODATA_PKT) { 30 | hdev->stat.sco_tx++; 31 | } 32 | 33 | hdev->stat.byte_tx += len; 34 | } 35 | } 36 | 37 | void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len) 38 | { 39 | if (hdev) { 40 | if (pkt_type == HCI_EVENT_PKT) { 41 | hdev->stat.evt_rx++; 42 | } else if (pkt_type == HCI_ACLDATA_PKT) { 43 | hdev->stat.acl_rx++; 44 | } else if (pkt_type == HCI_SCODATA_PKT) { 45 | hdev->stat.sco_rx++; 46 | } 47 | 48 | hdev->stat.byte_rx += len; 49 | } 50 | } 51 | 52 | static int esp_bt_open(struct hci_dev *hdev) 53 | { 54 | return 0; 55 | } 56 | 57 | static int esp_bt_close(struct hci_dev *hdev) 58 | { 59 | return 0; 60 | } 61 | 62 | static int esp_bt_flush(struct hci_dev *hdev) 63 | { 64 | return 0; 65 | } 66 | 67 | static int esp_bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 68 | { 69 | struct esp_payload_header *hdr; 70 | size_t total_len, len = skb->len; 71 | int ret = 0; 72 | struct esp_adapter *adapter = hci_get_drvdata(hdev); 73 | struct sk_buff *new_skb; 74 | 75 | if (!adapter) { 76 | printk(KERN_ERR "%s: invalid args", __func__); 77 | return -EINVAL; 78 | } 79 | 80 | total_len = len + sizeof(struct esp_payload_header); 81 | 82 | if (skb_headroom(skb) < sizeof(struct esp_payload_header)) { 83 | /* insufficent headroom to add payload header */ 84 | new_skb = skb_realloc_headroom(skb, sizeof(struct esp_payload_header)); 85 | 86 | if(!new_skb) { 87 | printk(KERN_ERR "%s: Failed to allocate SKB", __func__); 88 | dev_kfree_skb(skb); 89 | hdev->stat.err_tx++; 90 | return -ENOMEM; 91 | } 92 | 93 | dev_kfree_skb(skb); 94 | 95 | skb = new_skb; 96 | } 97 | 98 | skb_push(skb, sizeof(struct esp_payload_header)); 99 | 100 | hdr = (struct esp_payload_header *) skb->data; 101 | 102 | memset (hdr, 0, sizeof(struct esp_payload_header)); 103 | 104 | hdr->if_type = ESP_HCI_IF; 105 | hdr->if_num = 0; 106 | hdr->len = cpu_to_le16(len); 107 | hdr->offset = cpu_to_le16(sizeof(struct esp_payload_header)); 108 | hdr->hci_pkt_type = hci_skb_pkt_type(skb); 109 | 110 | /* print_hex_dump_bytes("Tx:", DUMP_PREFIX_NONE, skb->data, skb->len);*/ 111 | ret = esp_send_packet(adapter, skb->data, skb->len); 112 | 113 | if (ret) { 114 | hdev->stat.err_tx++; 115 | } else { 116 | esp_hci_update_tx_counter(hdev, hdr->hci_pkt_type, skb->len); 117 | } 118 | 119 | dev_kfree_skb(skb); 120 | 121 | return 0; 122 | } 123 | 124 | static int esp_bt_setup(struct hci_dev *hdev) 125 | { 126 | return 0; 127 | } 128 | 129 | static int esp_bt_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) 130 | { 131 | return 0; 132 | } 133 | 134 | int esp_deinit_bt(struct esp_adapter *adapter) 135 | { 136 | struct hci_dev *hdev = NULL; 137 | 138 | if (!adapter || !adapter->hcidev) 139 | return 0; 140 | 141 | hdev = adapter->hcidev; 142 | 143 | hci_unregister_dev(hdev); 144 | hci_free_dev(hdev); 145 | 146 | adapter->hcidev = NULL; 147 | 148 | return 0; 149 | } 150 | 151 | int esp_init_bt(struct esp_adapter *adapter) 152 | { 153 | int ret = 0; 154 | struct hci_dev *hdev = NULL; 155 | 156 | if (!adapter) { 157 | return -EINVAL; 158 | } 159 | 160 | if (adapter->hcidev) { 161 | return -EEXIST; 162 | } 163 | 164 | hdev = hci_alloc_dev(); 165 | 166 | if (!hdev) { 167 | BT_ERR("Can not allocate HCI device"); 168 | return -ENOMEM; 169 | } 170 | 171 | adapter->hcidev = hdev; 172 | hci_set_drvdata(hdev, adapter); 173 | 174 | if (adapter->if_type == ESP_IF_TYPE_SDIO) 175 | hdev->bus = HCI_SDIO; 176 | else if (adapter->if_type == ESP_IF_TYPE_SPI) 177 | hdev->bus = HCI_SPI; 178 | 179 | hdev->open = esp_bt_open; 180 | hdev->close = esp_bt_close; 181 | hdev->flush = esp_bt_flush; 182 | hdev->send = esp_bt_send_frame; 183 | hdev->setup = esp_bt_setup; 184 | hdev->set_bdaddr = esp_bt_set_bdaddr; 185 | 186 | hdev->dev_type = HCI_PRIMARY; 187 | 188 | ret = hci_register_dev(hdev); 189 | if (ret < 0) { 190 | BT_ERR("Can not register HCI device"); 191 | hci_free_dev(hdev); 192 | return -ENOMEM; 193 | } 194 | 195 | return 0; 196 | } 197 | -------------------------------------------------------------------------------- /esp_bt_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef __esp_bt_api_h_ 21 | #define __esp_bt_api_h_ 22 | 23 | #include 24 | #include "esp.h" 25 | 26 | 27 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)) 28 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)) 29 | #define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type 30 | #else 31 | #error "No symbol bt_cb((skb))->pkt_type in kernel < 2.6.14" 32 | #endif 33 | #endif 34 | 35 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) 36 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) 37 | #define HCI_PRIMARY HCI_BREDR 38 | #else 39 | #error "No symbol HCI_BREDR found in kernel < 2.6.34" 40 | #endif 41 | #endif 42 | 43 | int esp_init_bt(struct esp_adapter *adapter); 44 | int esp_deinit_bt(struct esp_adapter *adapter); 45 | void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len); 46 | void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /esp_if.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef __ESP_IF__H_ 21 | #define __ESP_IF__H_ 22 | 23 | #include "esp.h" 24 | 25 | struct esp_if_ops { 26 | int (*init)(struct esp_adapter *adapter); 27 | struct sk_buff* (*read)(struct esp_adapter *adapter); 28 | int (*write)(struct esp_adapter *adapter, u8 *buf, u32 size); 29 | int (*deinit)(struct esp_adapter *adapter); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /esp_rb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The citation should list that the code comes from the book "Linux Device 3 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 4 | * by O'Reilly & Associates.No warranty is attached; 5 | * 6 | * */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "esp_rb.h" 17 | 18 | int esp_rb_init(esp_rb_t *rb, size_t sz) 19 | { 20 | init_waitqueue_head(&(rb->wq)); 21 | 22 | rb->buf = kmalloc(sz, GFP_KERNEL); 23 | if (!rb->buf) { 24 | printk(KERN_ERR "Failed to allocate memory for rb\n"); 25 | return -ENOMEM; 26 | } 27 | 28 | rb->end = rb->buf + sz; 29 | rb->rp = rb->wp = rb->buf; 30 | rb->size = sz; 31 | 32 | sema_init(&(rb->sem), 1); 33 | return 0; 34 | } 35 | 36 | ssize_t esp_rb_read_by_user(esp_rb_t *rb, const char __user *buf, size_t sz, int block) 37 | { 38 | if (down_interruptible(&rb->sem)) { 39 | return -ERESTARTSYS; /* Signal interruption */ 40 | } 41 | 42 | while(rb->rp == rb->wp) { 43 | up(&rb->sem); 44 | if (block == 0) { 45 | return -EAGAIN; 46 | } 47 | if (wait_event_interruptible(rb->wq, (rb->rp != rb->wp))) { 48 | return -ERESTARTSYS; /* Signal interruption */ 49 | } 50 | if (down_interruptible(&rb->sem)) { 51 | return -ERESTARTSYS; 52 | } 53 | } 54 | 55 | if (rb->wp > rb->rp) { 56 | sz = min(sz, (size_t)(rb->wp - rb->rp)); 57 | } else { 58 | sz = min(sz, (size_t)(rb->end - rb->rp)); 59 | } 60 | if (copy_to_user((void *)buf, rb->rp, sz)) { 61 | up(&rb->sem); 62 | return -EFAULT; 63 | } 64 | rb->rp += sz; 65 | if (rb->rp == rb->end) { 66 | rb->rp = rb->buf; 67 | } 68 | up(&rb->sem); 69 | 70 | return sz; 71 | } 72 | 73 | static size_t get_free_space(esp_rb_t *rb) 74 | { 75 | if (rb->rp == rb->wp) { 76 | return rb->size - 1; 77 | } else { 78 | return ((rb->rp + rb->size - rb->wp) % rb->size) - 1; 79 | } 80 | } 81 | 82 | ssize_t esp_rb_write_by_kernel(esp_rb_t *rb, const char *buf, size_t sz) 83 | { 84 | if (down_interruptible(&rb->sem)) { 85 | return -ERESTARTSYS; 86 | } 87 | 88 | if (get_free_space(rb) == 0) { 89 | up(&rb->sem); 90 | printk(KERN_ERR "Ringbuffer full, no space to write\n"); 91 | return 0; 92 | } 93 | 94 | sz = min(sz, get_free_space(rb)); 95 | if (rb->wp >= rb->rp) { 96 | sz = min(sz, (size_t)(rb->end - rb->wp)); 97 | } else { 98 | sz = min(sz, (size_t)(rb->rp - rb->wp - 1)); 99 | } 100 | 101 | memcpy(rb->wp, buf, sz); 102 | rb->wp += sz; 103 | if (rb->wp == rb->end) { 104 | rb->wp = rb->buf; 105 | } 106 | up(&rb->sem); 107 | 108 | wake_up_interruptible(&rb->wq); 109 | 110 | return sz; 111 | } 112 | 113 | void esp_rb_cleanup(esp_rb_t *rb) 114 | { 115 | kfree(rb->buf); 116 | rb->buf = rb->end = rb->rp = rb->wp = NULL; 117 | rb->size = 0; 118 | return; 119 | } 120 | -------------------------------------------------------------------------------- /esp_rb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The citation should list that the code comes from the book "Linux Device 3 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published 4 | * by O'Reilly & Associates.No warranty is attached; 5 | * 6 | * */ 7 | 8 | #ifndef _ESP_RB_H_ 9 | #define _ESP_RB_H_ 10 | 11 | typedef struct esp_rb { 12 | wait_queue_head_t wq; /* waitqueue to wait for data */ 13 | unsigned char *buf, *end; /* actual queue start and end */ 14 | size_t size; 15 | unsigned char *rp, *wp; /* current read/write pointers */ 16 | struct semaphore sem; /* Mutex to protect rb */ 17 | } esp_rb_t; 18 | 19 | int esp_rb_init(esp_rb_t *rb, size_t sz); 20 | void esp_rb_cleanup(esp_rb_t *rb); 21 | ssize_t esp_rb_read_by_user(esp_rb_t *rb, const char __user *buf, size_t sz, int block); 22 | ssize_t esp_rb_write_by_kernel(esp_rb_t *rb, const char *buf, size_t sz); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /esp_serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "esp.h" 31 | #include "esp_rb.h" 32 | #include "esp_api.h" 33 | 34 | #define ESP_SERIAL_MAJOR 221 35 | #define ESP_SERIAL_MINOR_MAX 2 36 | #define ESP_RX_RB_SIZE 4096 37 | 38 | //#define ESP_SERIAL_TEST 39 | 40 | bool initialized = false; 41 | static struct esp_serial_devs { 42 | struct cdev cdev; 43 | int dev_index; 44 | esp_rb_t rb; 45 | void *priv; 46 | } devs[ESP_SERIAL_MINOR_MAX]; 47 | 48 | static ssize_t esp_serial_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset) 49 | { 50 | struct esp_serial_devs *dev; 51 | dev = (struct esp_serial_devs *) file->private_data; 52 | size = esp_rb_read_by_user(&dev->rb, user_buffer, size, file->f_flags & O_NONBLOCK); 53 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, user_buffer, size);*/ 54 | if (size == 0) { 55 | return -EAGAIN; 56 | } 57 | 58 | return size; 59 | } 60 | 61 | static ssize_t esp_serial_write(struct file *file, const char __user *user_buffer, size_t size, loff_t * offset) 62 | { 63 | struct esp_payload_header *hdr; 64 | char *buf; 65 | struct esp_serial_devs *dev; 66 | int ret; 67 | size_t total_len; 68 | 69 | dev = (struct esp_serial_devs *) file->private_data; 70 | total_len = size + sizeof(struct esp_payload_header); 71 | 72 | buf = kmalloc(total_len, GFP_KERNEL); 73 | if (!buf) { 74 | printk(KERN_ERR "Error allocating buffer to send serial data\n"); 75 | return -ENOMEM; 76 | } 77 | 78 | hdr = (struct esp_payload_header *) buf; 79 | 80 | memset (hdr, 0, sizeof(struct esp_payload_header)); 81 | 82 | hdr->if_type = ESP_SERIAL_IF; 83 | hdr->if_num = dev->dev_index; 84 | hdr->len = cpu_to_le16(size); 85 | hdr->offset = cpu_to_le16(sizeof(struct esp_payload_header)); 86 | 87 | ret = copy_from_user(buf + hdr->offset, user_buffer, size); 88 | if (ret != 0) { 89 | kfree(buf); 90 | printk(KERN_ERR "Error copying buffer to send serial data\n"); 91 | return -EFAULT; 92 | } 93 | 94 | ret = esp_send_packet(dev->priv, buf, total_len); 95 | if (ret) { 96 | printk (KERN_ERR "%s: Failed to transmit data\n", __func__); 97 | } 98 | 99 | kfree(buf); 100 | return size; 101 | } 102 | 103 | static long esp_serial_ioctl (struct file *file, unsigned int cmd, unsigned long arg) 104 | { 105 | printk(KERN_INFO "%s IOCTL %d\n", __func__, cmd); 106 | return 0; 107 | } 108 | 109 | static int esp_serial_open(struct inode *inode, struct file *file) 110 | { 111 | struct esp_serial_devs *devs; 112 | 113 | devs = container_of(inode->i_cdev, struct esp_serial_devs, cdev); 114 | file->private_data = devs; 115 | 116 | return 0; 117 | } 118 | 119 | const struct file_operations esp_serial_fops = { 120 | .owner = THIS_MODULE, 121 | .open = esp_serial_open, 122 | .read = esp_serial_read, 123 | .write = esp_serial_write, 124 | .unlocked_ioctl = esp_serial_ioctl 125 | }; 126 | 127 | int esp_serial_data_received(int dev_index, const char *data, size_t len) 128 | { 129 | int ret; 130 | size_t ret_len = 0; 131 | 132 | while (ret_len != len) { 133 | ret = esp_rb_write_by_kernel(&devs[dev_index].rb, data, len); 134 | ret_len += ret; 135 | if (ret == 0) { 136 | break; 137 | } 138 | } 139 | if (ret_len != len) { 140 | printk(KERN_ERR "RB full, no space to receive. Dropping packet"); 141 | } 142 | 143 | return ret_len; 144 | } 145 | 146 | #ifdef ESP_SERIAL_TEST 147 | static int thread_fn(void *unused) 148 | { 149 | int i = 100; 150 | 151 | while(i--) { 152 | esp_rb_write_by_kernel(&devs[0].rb, "alphabetagamma", 14); 153 | ssleep(1); 154 | } 155 | printk(KERN_INFO "Thread stopping\n"); 156 | do_exit(0); 157 | return 0; 158 | } 159 | #endif 160 | 161 | int esp_serial_init(void *priv) 162 | { 163 | int err; 164 | int i; 165 | 166 | err = register_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX, "esp_serial_driver"); 167 | if (err) { 168 | printk(KERN_ERR "Error registering chrdev region %d\n", err); 169 | return -1; 170 | } 171 | 172 | for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) { 173 | cdev_init(&devs[i].cdev, &esp_serial_fops); 174 | devs[i].dev_index = i; 175 | cdev_add(&devs[i].cdev, MKDEV(ESP_SERIAL_MAJOR, i), 1); 176 | esp_rb_init(&devs[i].rb, ESP_RX_RB_SIZE); 177 | devs[i].priv = priv; 178 | } 179 | 180 | #ifdef ESP_SERIAL_TEST 181 | kthread_run(thread_fn, NULL, "esptest-thread"); 182 | #endif 183 | initialized = true; 184 | 185 | return 0; 186 | } 187 | 188 | void esp_serial_cleanup(void) 189 | { 190 | int i; 191 | if (!initialized) 192 | return; 193 | for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) { 194 | cdev_del(&devs[i].cdev); 195 | esp_rb_cleanup(&devs[i].rb); 196 | } 197 | unregister_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX); 198 | } 199 | -------------------------------------------------------------------------------- /esp_serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef _ESP_SERIAL_H_ 21 | #define _ESP_SERIAL_H_ 22 | 23 | int esp_serial_init(void * priv); 24 | void esp_serial_cleanup(void); 25 | 26 | int esp_serial_data_received(int dev_index, const char *data, size_t len); 27 | #endif 28 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "esp.h" 31 | #include "esp_if.h" 32 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 33 | #include "esp_serial.h" 34 | #endif 35 | #include "esp_bt_api.h" 36 | 37 | struct esp_adapter adapter; 38 | volatile u8 stop_data = 0; 39 | 40 | #define ACTION_DROP 1 41 | static int esp_open(struct net_device *ndev); 42 | static int esp_stop(struct net_device *ndev); 43 | static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev); 44 | static int esp_set_mac_address(struct net_device *ndev, void *addr); 45 | static void esp_tx_timeout(struct net_device *ndev); 46 | static struct net_device_stats* esp_get_stats(struct net_device *ndev); 47 | static void esp_set_rx_mode(struct net_device *ndev); 48 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size); 49 | 50 | static const struct net_device_ops esp_netdev_ops = { 51 | .ndo_open = esp_open, 52 | .ndo_stop = esp_stop, 53 | .ndo_start_xmit = esp_hard_start_xmit, 54 | .ndo_set_mac_address = esp_set_mac_address, 55 | .ndo_validate_addr = eth_validate_addr, 56 | .ndo_tx_timeout = esp_tx_timeout, 57 | .ndo_get_stats = esp_get_stats, 58 | .ndo_set_rx_mode = esp_set_rx_mode, 59 | }; 60 | 61 | #if 0 62 | u64 start_time, end_time; 63 | #endif 64 | 65 | struct esp_adapter * esp_get_adapter(void) 66 | { 67 | return &adapter; 68 | } 69 | 70 | static int esp_open(struct net_device *ndev) 71 | { 72 | netif_start_queue(ndev); 73 | return 0; 74 | } 75 | 76 | static int esp_stop(struct net_device *ndev) 77 | { 78 | netif_stop_queue(ndev); 79 | return 0; 80 | } 81 | 82 | static struct net_device_stats* esp_get_stats(struct net_device *ndev) 83 | { 84 | struct esp_private *priv = netdev_priv(ndev); 85 | return &priv->stats; 86 | } 87 | 88 | static int esp_set_mac_address(struct net_device *ndev, void *data) 89 | { 90 | struct esp_private *priv = netdev_priv(ndev); 91 | struct sockaddr *mac_addr = data; 92 | 93 | if (!priv) 94 | return -EINVAL; 95 | 96 | ether_addr_copy(priv->mac_address, mac_addr->sa_data); 97 | ether_addr_copy(ndev->dev_addr, mac_addr->sa_data); 98 | return 0; 99 | } 100 | 101 | static void esp_tx_timeout(struct net_device *ndev) 102 | { 103 | } 104 | 105 | static void esp_set_rx_mode(struct net_device *ndev) 106 | { 107 | } 108 | 109 | static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) 110 | { 111 | struct sk_buff *new_skb; 112 | struct esp_private *priv = netdev_priv(ndev); 113 | struct esp_skb_cb *cb; 114 | 115 | if (!priv) { 116 | dev_kfree_skb(skb); 117 | return -EINVAL; 118 | } 119 | 120 | if (!skb->len || (skb->len > ETH_FRAME_LEN)) { 121 | printk (KERN_ERR "%s: Bad len %d\n", __func__, skb->len); 122 | priv->stats.tx_dropped++; 123 | dev_kfree_skb(skb); 124 | return -EINVAL; 125 | } 126 | 127 | if (skb_headroom(skb) < ESP_PAYLOAD_HEADER) { 128 | /* Insufficient space. Realloc skb. */ 129 | new_skb = skb_realloc_headroom(skb, ESP_PAYLOAD_HEADER); 130 | 131 | if (unlikely(!new_skb)) { 132 | printk (KERN_ERR "%s: Failed to allocate SKB\n", __func__); 133 | priv->stats.tx_dropped++; 134 | dev_kfree_skb(skb); 135 | return -ENOMEM; 136 | } 137 | 138 | /* Free old SKB */ 139 | dev_kfree_skb(skb); 140 | 141 | skb = new_skb; 142 | } 143 | 144 | cb = (struct esp_skb_cb *) skb->cb; 145 | cb->priv = priv; 146 | 147 | /* print_hex_dump_bytes("Tx:", DUMP_PREFIX_NONE, skb->data, 8);*/ 148 | 149 | skb_queue_tail(&adapter.tx_q, skb); 150 | atomic_inc(&adapter.tx_pending); 151 | queue_work(adapter.tx_workqueue, &adapter.tx_work); 152 | 153 | return 0; 154 | } 155 | 156 | u8 esp_is_bt_supported_over_sdio(u32 cap) 157 | { 158 | return (cap & ESP_BT_SDIO_SUPPORT); 159 | } 160 | 161 | static struct esp_private * get_priv_from_payload_header(struct esp_payload_header *header) 162 | { 163 | struct esp_private *priv; 164 | u8 i; 165 | 166 | if (!header) 167 | return NULL; 168 | 169 | for (i = 0; i < ESP_MAX_INTERFACE; i++) { 170 | priv = adapter.priv[i]; 171 | 172 | if (!priv) 173 | continue; 174 | 175 | if (priv->if_type == header->if_type && 176 | priv->if_num == header->if_num) { 177 | return priv; 178 | } 179 | } 180 | 181 | return NULL; 182 | } 183 | 184 | void esp_process_new_packet_intr(struct esp_adapter *adapter) 185 | { 186 | if(adapter) 187 | queue_work(adapter->if_rx_workqueue, &adapter->if_rx_work); 188 | } 189 | 190 | static void process_tx_packet (void) 191 | { 192 | struct sk_buff *skb; 193 | struct esp_private *priv; 194 | struct esp_skb_cb *cb; 195 | struct esp_payload_header *payload_header; 196 | struct sk_buff *new_skb; 197 | int ret = 0; 198 | u8 pad_len = 0; 199 | u16 len = 0; 200 | static u32 c = 0; 201 | 202 | while ((skb = skb_dequeue(&adapter.tx_q))) { 203 | c++; 204 | /* Get the priv */ 205 | cb = (struct esp_skb_cb *) skb->cb; 206 | priv = cb->priv; 207 | 208 | if (!priv) { 209 | dev_kfree_skb_any(skb); 210 | atomic_dec(&adapter.tx_pending); 211 | continue; 212 | } 213 | 214 | len = skb->len; 215 | 216 | /* Create space for payload header */ 217 | pad_len = sizeof(struct esp_payload_header); 218 | 219 | if (skb_headroom(skb) < pad_len) { 220 | /* insufficent headroom to add payload header */ 221 | new_skb = skb_realloc_headroom(skb, pad_len); 222 | 223 | if(!new_skb) { 224 | printk(KERN_ERR "%s: Failed to allocate SKB", __func__); 225 | dev_kfree_skb(skb); 226 | atomic_dec(&adapter.tx_pending); 227 | continue; 228 | } 229 | 230 | dev_kfree_skb(skb); 231 | 232 | skb = new_skb; 233 | } 234 | 235 | skb_push(skb, pad_len); 236 | 237 | /* Set payload header */ 238 | payload_header = (struct esp_payload_header *) skb->data; 239 | memset(payload_header, 0, pad_len); 240 | 241 | payload_header->if_type = priv->if_type; 242 | payload_header->if_num = priv->if_num; 243 | payload_header->len = cpu_to_le16(skb->len - pad_len); 244 | payload_header->offset = cpu_to_le16(pad_len); 245 | payload_header->reserved1 = c % 255; 246 | 247 | /* printk (KERN_ERR "H -> S: %d %d %d %d", len, payload_header->offset,*/ 248 | /* payload_header->len, payload_header->reserved1);*/ 249 | 250 | if (!stop_data) { 251 | ret = esp_send_packet(priv->adapter, skb->data, skb->len); 252 | 253 | if (ret) { 254 | priv->stats.tx_errors++; 255 | } else { 256 | priv->stats.tx_packets++; 257 | priv->stats.tx_bytes += skb->len; 258 | } 259 | } else { 260 | priv->stats.tx_dropped++; 261 | } 262 | 263 | dev_kfree_skb_any(skb); 264 | atomic_dec(&adapter.tx_pending); 265 | } 266 | } 267 | 268 | static void process_rx_packet(struct sk_buff *skb) 269 | { 270 | struct esp_private *priv; 271 | struct esp_payload_header *payload_header; 272 | u16 len, offset; 273 | struct hci_dev *hdev = adapter.hcidev; 274 | u8 *type; 275 | 276 | if (!skb) 277 | return; 278 | 279 | /* get the paload header */ 280 | payload_header = (struct esp_payload_header *) skb->data; 281 | 282 | len = le16_to_cpu(payload_header->len); 283 | offset = le16_to_cpu(payload_header->offset); 284 | 285 | if (payload_header->if_type == ESP_SERIAL_IF) { 286 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 287 | esp_serial_data_received(payload_header->if_num, skb->data + offset, len); 288 | #else 289 | printk(KERN_ERR "Dropping unsupported serial frame\n"); 290 | #endif 291 | dev_kfree_skb_any(skb); 292 | } else if (payload_header->if_type == ESP_STA_IF || payload_header->if_type == ESP_AP_IF) { 293 | /* chop off the header from skb */ 294 | skb_pull(skb, offset); 295 | 296 | /* retrieve priv based on payload header contents */ 297 | priv = get_priv_from_payload_header(payload_header); 298 | 299 | if (!priv) { 300 | printk (KERN_ERR "%s: empty priv\n", __func__); 301 | dev_kfree_skb_any(skb); 302 | /* atomic_dec(&adapter.rx_pending);*/ 303 | return; 304 | } 305 | 306 | skb->dev = priv->ndev; 307 | skb->protocol = eth_type_trans(skb, priv->ndev); 308 | skb->ip_summed = CHECKSUM_NONE; 309 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, 8);*/ 310 | 311 | /* Forward skb to kernel */ 312 | netif_rx(skb); 313 | 314 | priv->stats.rx_bytes += skb->len; 315 | priv->stats.rx_packets++; 316 | } else if (payload_header->if_type == ESP_HCI_IF) { 317 | if (hdev) { 318 | /* chop off the header from skb */ 319 | skb_pull(skb, offset); 320 | 321 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, skb->len);*/ 322 | type = skb->data; 323 | hci_skb_pkt_type(skb) = *type; 324 | skb_pull(skb, 1); 325 | 326 | if (hci_recv_frame(hdev, skb)) { 327 | hdev->stat.err_rx++; 328 | } else { 329 | esp_hci_update_rx_counter(hdev, *type, skb->len); 330 | } 331 | } 332 | } 333 | } 334 | 335 | struct sk_buff * esp_alloc_skb(u32 len) 336 | { 337 | struct sk_buff *skb; 338 | 339 | skb = netdev_alloc_skb(NULL, len); 340 | return skb; 341 | } 342 | 343 | 344 | static int esp_get_packets(struct esp_adapter *adapter) 345 | { 346 | struct sk_buff *skb; 347 | 348 | if (!adapter || !adapter->if_ops || !adapter->if_ops->read) 349 | return -EINVAL; 350 | 351 | skb = adapter->if_ops->read(adapter); 352 | 353 | if (!skb) 354 | return -EFAULT; 355 | 356 | process_rx_packet(skb); 357 | 358 | return 0; 359 | } 360 | 361 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size) 362 | { 363 | if (!adapter || !adapter->if_ops || !adapter->if_ops->write) 364 | return -EINVAL; 365 | 366 | return adapter->if_ops->write(adapter, buf, size); 367 | } 368 | 369 | static int insert_priv_to_adapter(struct esp_private *priv) 370 | { 371 | int i = 0; 372 | 373 | for (i = 0; i < ESP_MAX_INTERFACE; i++) { 374 | /* Check if priv can be added */ 375 | if (adapter.priv[i] == NULL) { 376 | adapter.priv[i] = priv; 377 | return 0; 378 | } 379 | } 380 | 381 | return -1; 382 | } 383 | 384 | static int esp_init_priv(struct esp_private *priv, struct net_device *dev, 385 | u8 if_type, u8 if_num) 386 | { 387 | int ret = 0; 388 | 389 | if (!priv || !dev) 390 | return -EINVAL; 391 | 392 | ret = insert_priv_to_adapter(priv); 393 | if (ret) 394 | return ret; 395 | 396 | priv->ndev = dev; 397 | priv->if_type = if_type; 398 | priv->if_num = if_num; 399 | priv->link_state = ESP_LINK_DOWN; 400 | priv->adapter = &adapter; 401 | memset(&priv->stats, 0, sizeof(priv->stats)); 402 | 403 | return 0; 404 | } 405 | 406 | static int esp_init_net_dev(struct net_device *ndev, struct esp_private *priv) 407 | { 408 | int ret = 0; 409 | /* Set netdev */ 410 | /* SET_NETDEV_DEV(ndev, &adapter->context.func->dev);*/ 411 | 412 | /* set net dev ops */ 413 | ndev->netdev_ops = &esp_netdev_ops; 414 | 415 | ether_addr_copy(ndev->dev_addr, priv->mac_address); 416 | /* set ethtool ops */ 417 | 418 | /* update features supported */ 419 | 420 | /* min mtu */ 421 | 422 | /* register netdev */ 423 | ret = register_netdev(ndev); 424 | 425 | /* netif_start_queue(ndev);*/ 426 | /* ndev->needs_free_netdev = true; */ 427 | 428 | /* set watchdog timeout */ 429 | 430 | return ret; 431 | } 432 | 433 | static int esp_add_interface(struct esp_adapter *adapter, u8 if_type, u8 if_num, char *name) 434 | { 435 | struct net_device *ndev = NULL; 436 | struct esp_private *priv = NULL; 437 | int ret = 0; 438 | 439 | ndev = alloc_netdev_mqs(sizeof(struct esp_private), name, 440 | NET_NAME_ENUM, ether_setup, 1, 1); 441 | 442 | if (!ndev) { 443 | printk(KERN_ERR "%s: alloc failed\n", __func__); 444 | return -ENOMEM; 445 | } 446 | 447 | priv = netdev_priv(ndev); 448 | 449 | /* Init priv */ 450 | ret = esp_init_priv(priv, ndev, if_type, if_num); 451 | if (ret) { 452 | printk(KERN_ERR "%s: Init priv failed\n", __func__); 453 | goto error_exit; 454 | } 455 | 456 | ret = esp_init_net_dev(ndev, priv); 457 | if (ret) { 458 | printk(KERN_ERR "%s: Init netdev failed\n", __func__); 459 | goto error_exit; 460 | } 461 | 462 | return ret; 463 | 464 | error_exit: 465 | free_netdev(ndev); 466 | return ret; 467 | } 468 | 469 | static void flush_ring_buffers(struct esp_adapter *adapter) 470 | { 471 | struct sk_buff *skb; 472 | 473 | printk (KERN_INFO "%s: Flush Pending SKBs: %d %d\n", __func__, 474 | atomic_read(&adapter->tx_pending), 475 | atomic_read(&adapter->rx_pending)); 476 | 477 | while ((skb = skb_dequeue(&adapter->tx_q))) { 478 | dev_kfree_skb_any(skb); 479 | atomic_dec(&adapter->tx_pending); 480 | } 481 | 482 | while ((skb = skb_dequeue(&adapter->rx_q))) { 483 | dev_kfree_skb_any(skb); 484 | atomic_dec(&adapter->rx_pending); 485 | } 486 | } 487 | 488 | static void esp_remove_network_interfaces(struct esp_adapter *adapter) 489 | { 490 | if (adapter->priv[0] && adapter->priv[0]->ndev) { 491 | netif_stop_queue(adapter->priv[0]->ndev); 492 | unregister_netdev(adapter->priv[0]->ndev); 493 | free_netdev(adapter->priv[0]->ndev); 494 | } 495 | 496 | if (adapter->priv[1] && adapter->priv[1]->ndev) { 497 | netif_stop_queue(adapter->priv[1]->ndev); 498 | unregister_netdev(adapter->priv[1]->ndev); 499 | free_netdev(adapter->priv[1]->ndev); 500 | } 501 | } 502 | 503 | int esp_add_card(struct esp_adapter *adapter) 504 | { 505 | int ret = 0; 506 | 507 | if (!adapter) { 508 | printk(KERN_ERR "%s: Invalid args\n", __func__); 509 | return -EINVAL; 510 | } 511 | 512 | stop_data = 0; 513 | 514 | /* Add interface STA and AP */ 515 | ret = esp_add_interface(adapter, ESP_STA_IF, 0, "ethsta%d"); 516 | if (ret) { 517 | printk(KERN_ERR "%s: Failed to add STA\n", __func__); 518 | return ret; 519 | } 520 | 521 | ret = esp_add_interface(adapter, ESP_AP_IF, 0, "ethap%d"); 522 | if (ret) { 523 | printk(KERN_ERR "%s: Failed to add AP\n", __func__); 524 | esp_remove_network_interfaces(adapter); 525 | } 526 | 527 | return ret; 528 | } 529 | 530 | int esp_remove_card(struct esp_adapter *adapter) 531 | { 532 | stop_data = 1; 533 | 534 | if (!adapter) 535 | return 0; 536 | 537 | /* Flush workqueues */ 538 | if (adapter->if_rx_workqueue) 539 | flush_workqueue(adapter->if_rx_workqueue); 540 | 541 | if (adapter->tx_workqueue) 542 | flush_workqueue(adapter->tx_workqueue); 543 | 544 | esp_remove_network_interfaces(adapter); 545 | 546 | flush_ring_buffers(adapter); 547 | 548 | adapter->priv[0] = NULL; 549 | adapter->priv[1] = NULL; 550 | 551 | atomic_set(&adapter->tx_pending, 0); 552 | atomic_set(&adapter->rx_pending, 0); 553 | 554 | return 0; 555 | } 556 | 557 | 558 | static void esp_tx_work (struct work_struct *work) 559 | { 560 | process_tx_packet(); 561 | } 562 | 563 | static void esp_if_rx_work (struct work_struct *work) 564 | { 565 | /* read inbound packet and forward it to network/serial interface */ 566 | esp_get_packets(&adapter); 567 | } 568 | 569 | void deinit_adapter(void) 570 | { 571 | if (adapter.if_rx_workqueue) 572 | destroy_workqueue(adapter.if_rx_workqueue); 573 | 574 | if (adapter.tx_workqueue) 575 | destroy_workqueue(adapter.tx_workqueue); 576 | } 577 | 578 | struct esp_adapter * init_adapter(void) 579 | { 580 | memset(&adapter, 0, sizeof(adapter)); 581 | 582 | /* Prepare interface RX work */ 583 | adapter.if_rx_workqueue = create_workqueue("ESP_IF_RX_WORK_QUEUE"); 584 | if (!adapter.if_rx_workqueue) { 585 | deinit_adapter(); 586 | return NULL; 587 | } 588 | 589 | INIT_WORK(&adapter.if_rx_work, esp_if_rx_work); 590 | 591 | /* Prepare TX work */ 592 | adapter.tx_workqueue = create_workqueue("ESP_TX_WORK_QUEUE"); 593 | if (!adapter.tx_workqueue) { 594 | deinit_adapter(); 595 | return NULL; 596 | } 597 | 598 | INIT_WORK(&adapter.tx_work, esp_tx_work); 599 | 600 | /* Prepare TX work */ 601 | skb_queue_head_init(&adapter.tx_q); 602 | skb_queue_head_init(&adapter.rx_q); 603 | 604 | atomic_set(&adapter.tx_pending, 0); 605 | atomic_set(&adapter.rx_pending, 0); 606 | 607 | return &adapter; 608 | } 609 | -------------------------------------------------------------------------------- /sdio/esp_sdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "esp_if.h" 27 | #include "esp_sdio_api.h" 28 | #include "esp_api.h" 29 | #include "esp_bt_api.h" 30 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 31 | #include "esp_serial.h" 32 | #endif 33 | #include 34 | 35 | #define CHECK_SDIO_RW_ERROR(ret) do { \ 36 | if (ret) \ 37 | printk(KERN_ERR "%s: CMD53 read/write error at %d\n", __func__, __LINE__); \ 38 | } while (0); 39 | 40 | struct esp_sdio_context sdio_context; 41 | 42 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS 43 | struct task_struct *monitor_thread; 44 | #endif 45 | 46 | static int init_context(struct esp_sdio_context *context); 47 | static struct sk_buff * read_packet(struct esp_adapter *adapter); 48 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size); 49 | /*int deinit_context(struct esp_adapter *adapter);*/ 50 | 51 | static const struct sdio_device_id esp_devices[] = { 52 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_1) }, 53 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_2) }, 54 | {} 55 | }; 56 | 57 | static void print_capabilities(u32 cap) 58 | { 59 | printk(KERN_INFO "Features supported are:\n"); 60 | if (cap & ESP_WLAN_SDIO_SUPPORT) 61 | printk(KERN_INFO "\t * WLAN\n"); 62 | if ((cap & ESP_BT_UART_SUPPORT) || (cap & ESP_BT_SDIO_SUPPORT)) { 63 | printk(KERN_INFO "\t * BT/BLE\n"); 64 | if (cap & ESP_BT_UART_SUPPORT) 65 | printk(KERN_INFO "\t - HCI over UART\n"); 66 | if (cap & ESP_BT_SDIO_SUPPORT) 67 | printk(KERN_INFO "\t - HCI over SDIO\n"); 68 | 69 | if ((cap & ESP_BLE_ONLY_SUPPORT) && (cap & ESP_BR_EDR_ONLY_SUPPORT)) 70 | printk(KERN_INFO "\t - BT/BLE dual mode\n"); 71 | else if (cap & ESP_BLE_ONLY_SUPPORT) 72 | printk(KERN_INFO "\t - BLE only\n"); 73 | else if (cap & ESP_BR_EDR_ONLY_SUPPORT) 74 | printk(KERN_INFO "\t - BR EDR only\n"); 75 | } 76 | } 77 | 78 | static void esp_process_interrupt(struct esp_sdio_context *context, u32 int_status) 79 | { 80 | if (!context) { 81 | return; 82 | } 83 | 84 | if (int_status & ESP_SLAVE_RX_NEW_PACKET_INT) { 85 | esp_process_new_packet_intr(context->adapter); 86 | } 87 | } 88 | 89 | static void esp_handle_isr(struct sdio_func *func) 90 | { 91 | struct esp_sdio_context *context = NULL; 92 | u32 int_status = 0; 93 | int ret; 94 | 95 | if (!func) { 96 | return; 97 | } 98 | 99 | context = sdio_get_drvdata(func); 100 | 101 | if (!context) { 102 | return; 103 | } 104 | 105 | /* Read interrupt status register */ 106 | ret = esp_read_reg(context, ESP_SLAVE_INT_ST_REG, 107 | (u8 *) &int_status, sizeof(int_status), ACQUIRE_LOCK); 108 | CHECK_SDIO_RW_ERROR(ret); 109 | 110 | esp_process_interrupt(context, int_status); 111 | 112 | /* Clear interrupt status */ 113 | ret = esp_write_reg(context, ESP_SLAVE_INT_CLR_REG, 114 | (u8 *) &int_status, sizeof(int_status), ACQUIRE_LOCK); 115 | CHECK_SDIO_RW_ERROR(ret); 116 | } 117 | 118 | int generate_slave_intr(struct esp_sdio_context *context, u8 data) 119 | { 120 | if (!context) 121 | return -EINVAL; 122 | 123 | return esp_write_reg(context, ESP_SLAVE_SCRATCH_REG_7, &data, 124 | sizeof(data), ACQUIRE_LOCK); 125 | } 126 | 127 | static void deinit_sdio_func(struct sdio_func *func) 128 | { 129 | sdio_claim_host(func); 130 | /* Release IRQ */ 131 | sdio_release_irq(func); 132 | /* Disable sdio function */ 133 | sdio_disable_func(func); 134 | sdio_release_host(func); 135 | sdio_set_drvdata(func, NULL); 136 | } 137 | 138 | static int esp_slave_get_tx_buffer_num(struct esp_sdio_context *context, u32 *tx_num, u8 is_lock_needed) 139 | { 140 | u32 len; 141 | int ret = 0; 142 | 143 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (uint8_t*)&len, 4, is_lock_needed); 144 | 145 | if (ret) 146 | return ret; 147 | 148 | len = (len >> 16) & ESP_TX_BUFFER_MASK; 149 | len = (len + ESP_TX_BUFFER_MAX - context->tx_buffer_count) % ESP_TX_BUFFER_MAX; 150 | 151 | *tx_num = len; 152 | 153 | return ret; 154 | } 155 | 156 | static int esp_get_len_from_slave(struct esp_sdio_context *context, u32 *rx_size, u8 is_lock_needed) 157 | { 158 | u32 len, temp; 159 | int ret = 0; 160 | 161 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, 162 | (u8 *) &len, sizeof(len), is_lock_needed); 163 | 164 | if (ret) 165 | return ret; 166 | 167 | len &= ESP_SLAVE_LEN_MASK; 168 | 169 | if (len >= context->rx_byte_count) 170 | len = (len + ESP_RX_BYTE_MAX - context->rx_byte_count) % ESP_RX_BYTE_MAX; 171 | else { 172 | /* Handle a case of roll over */ 173 | temp = ESP_RX_BYTE_MAX - context->rx_byte_count; 174 | len = temp + len; 175 | 176 | if (len > ESP_RX_BUFFER_SIZE) { 177 | printk(KERN_INFO "%s: Len from slave[%d] exceeds max [%d]\n", 178 | __func__, len, ESP_RX_BUFFER_SIZE); 179 | } 180 | } 181 | *rx_size = len; 182 | 183 | return 0; 184 | } 185 | 186 | 187 | static void flush_sdio(struct esp_sdio_context *context) 188 | { 189 | struct sk_buff *skb; 190 | 191 | if (!context || !context->adapter) 192 | return; 193 | 194 | while (1) { 195 | skb = read_packet(context->adapter); 196 | 197 | if (!skb) { 198 | break; 199 | } 200 | 201 | if (skb->len) 202 | printk (KERN_INFO "%s: Flushed %d bytes\n", __func__, skb->len); 203 | dev_kfree_skb(skb); 204 | } 205 | } 206 | 207 | static void esp_remove(struct sdio_func *func) 208 | { 209 | struct esp_sdio_context *context; 210 | context = sdio_get_drvdata(func); 211 | 212 | printk(KERN_INFO "%s -> Remove card", __func__); 213 | 214 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 215 | esp_serial_cleanup(); 216 | #endif 217 | 218 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS 219 | if (monitor_thread) 220 | kthread_stop(monitor_thread); 221 | #endif 222 | 223 | if (context) { 224 | generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH)); 225 | msleep(100); 226 | 227 | flush_sdio(context); 228 | 229 | if (context->adapter) { 230 | esp_remove_card(context->adapter); 231 | 232 | if (context->adapter->hcidev) { 233 | esp_deinit_bt(context->adapter); 234 | } 235 | 236 | } 237 | 238 | memset(context, 0, sizeof(struct esp_sdio_context)); 239 | } 240 | 241 | deinit_sdio_func(func); 242 | 243 | printk (KERN_INFO "%s: Context deinit %d - %d\n", __func__, context->rx_byte_count, 244 | context->tx_buffer_count); 245 | 246 | } 247 | 248 | static struct esp_if_ops if_ops = { 249 | .read = read_packet, 250 | .write = write_packet, 251 | }; 252 | 253 | static int init_context(struct esp_sdio_context *context) 254 | { 255 | int ret = 0; 256 | u32 val = 0; 257 | 258 | if (!context) { 259 | return -EINVAL; 260 | } 261 | 262 | /* Initialize rx_byte_count */ 263 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, 264 | (u8 *) &val, sizeof(val), ACQUIRE_LOCK); 265 | if (ret) 266 | return ret; 267 | 268 | /* printk(KERN_DEBUG "%s: LEN %d\n", __func__, (val & ESP_SLAVE_LEN_MASK));*/ 269 | 270 | context->rx_byte_count = val & ESP_SLAVE_LEN_MASK; 271 | 272 | /* Initialize tx_buffer_count */ 273 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) &val, 274 | sizeof(val), ACQUIRE_LOCK); 275 | 276 | if (ret) 277 | return ret; 278 | 279 | val = ((val >> 16) & ESP_TX_BUFFER_MASK); 280 | 281 | /* printk(KERN_DEBUG "%s: BUF_CNT %d\n", __func__, val);*/ 282 | 283 | if (val >= ESP_MAX_BUF_CNT) 284 | context->tx_buffer_count = val - ESP_MAX_BUF_CNT; 285 | else 286 | context->tx_buffer_count = 0; 287 | 288 | /* printk(KERN_DEBUG "%s: Context init %d - %d\n", __func__, context->rx_byte_count,*/ 289 | /* context->tx_buffer_count);*/ 290 | 291 | context->adapter = esp_get_adapter(); 292 | 293 | if (!context->adapter) 294 | printk (KERN_ERR "%s: Failed to get adapter\n", __func__); 295 | 296 | context->adapter->if_type = ESP_IF_TYPE_SDIO; 297 | 298 | return ret; 299 | } 300 | 301 | static struct sk_buff * read_packet(struct esp_adapter *adapter) 302 | { 303 | u32 len_from_slave, data_left, len_to_read, size, num_blocks; 304 | int ret = 0; 305 | struct sk_buff *skb; 306 | u8 *pos; 307 | struct esp_sdio_context *context; 308 | 309 | if (!adapter || !adapter->if_context) { 310 | printk (KERN_ERR "%s: INVALID args\n", __func__); 311 | return NULL; 312 | } 313 | 314 | context = adapter->if_context; 315 | 316 | sdio_claim_host(context->func); 317 | 318 | data_left = len_to_read = len_from_slave = num_blocks = 0; 319 | 320 | /* Read length */ 321 | ret = esp_get_len_from_slave(context, &len_from_slave, LOCK_ALREADY_ACQUIRED); 322 | 323 | /* printk (KERN_DEBUG "LEN FROM SLAVE: %d\n", len_from_slave);*/ 324 | 325 | if (ret || !len_from_slave) { 326 | sdio_release_host(context->func); 327 | return NULL; 328 | } 329 | 330 | size = ESP_BLOCK_SIZE * 4; 331 | 332 | if (len_from_slave > size) { 333 | printk(KERN_INFO "Rx large packet: %d\n", len_from_slave); 334 | } 335 | 336 | skb = esp_alloc_skb(len_from_slave); 337 | 338 | if (!skb) { 339 | printk (KERN_ERR "%s: SKB alloc failed\n", __func__); 340 | sdio_release_host(context->func); 341 | return NULL; 342 | } 343 | 344 | skb_put(skb, len_from_slave); 345 | pos = skb->data; 346 | 347 | data_left = len_from_slave; 348 | 349 | do { 350 | num_blocks = data_left/ESP_BLOCK_SIZE; 351 | 352 | #if 0 353 | if (!context->rx_byte_count) { 354 | start_time = ktime_get_ns(); 355 | } 356 | #endif 357 | 358 | if (num_blocks) { 359 | len_to_read = num_blocks * ESP_BLOCK_SIZE; 360 | ret = esp_read_block(context, 361 | ESP_SLAVE_CMD53_END_ADDR - len_to_read, 362 | pos, len_to_read, LOCK_ALREADY_ACQUIRED); 363 | } else { 364 | len_to_read = data_left; 365 | /* 4 byte aligned length */ 366 | ret = esp_read_block(context, 367 | ESP_SLAVE_CMD53_END_ADDR - len_to_read, 368 | pos, (len_to_read + 3) & (~3), LOCK_ALREADY_ACQUIRED); 369 | } 370 | 371 | if (ret) { 372 | printk (KERN_ERR "%s: Failed to read data\n", __func__); 373 | dev_kfree_skb(skb); 374 | sdio_release_host(context->func); 375 | return NULL; 376 | } 377 | 378 | data_left -= len_to_read; 379 | pos += len_to_read; 380 | context->rx_byte_count += len_to_read; 381 | context->rx_byte_count = context->rx_byte_count % ESP_RX_BYTE_MAX; 382 | 383 | } while (data_left > 0); 384 | 385 | sdio_release_host(context->func); 386 | 387 | return skb; 388 | } 389 | 390 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size) 391 | { 392 | u32 block_cnt = 0, buf_needed = 0; 393 | u32 buf_available = 0; 394 | int ret = 0; 395 | u8 *pos = NULL; 396 | u32 data_left, len_to_send, pad; 397 | struct esp_sdio_context *context; 398 | 399 | if (!adapter || !adapter->if_context || !buf || !size) { 400 | printk (KERN_ERR "%s: Invalid args\n", __func__); 401 | return -EINVAL; 402 | } 403 | 404 | context = adapter->if_context; 405 | 406 | sdio_claim_host(context->func); 407 | 408 | buf_needed = (size + ESP_RX_BUFFER_SIZE - 1) / ESP_RX_BUFFER_SIZE; 409 | 410 | ret = esp_slave_get_tx_buffer_num(context, &buf_available, LOCK_ALREADY_ACQUIRED); 411 | 412 | /* printk(KERN_ERR "%s: TX -> Available [%d], needed [%d]\n", __func__, buf_available, buf_needed);*/ 413 | 414 | if (buf_available < buf_needed) { 415 | printk(KERN_DEBUG "%s: Not enough buffers available: availabale [%d], needed [%d]\n", __func__, 416 | buf_available, buf_needed); 417 | sdio_release_host(context->func); 418 | return -ENOMEM; 419 | } 420 | 421 | pos = buf; 422 | data_left = len_to_send = 0; 423 | 424 | data_left = size; 425 | pad = ESP_BLOCK_SIZE - (data_left % ESP_BLOCK_SIZE); 426 | data_left += pad; 427 | 428 | 429 | do { 430 | block_cnt = data_left / ESP_BLOCK_SIZE; 431 | len_to_send = data_left; 432 | ret = esp_write_block(context, ESP_SLAVE_CMD53_END_ADDR - len_to_send, 433 | pos, (len_to_send + 3) & (~3), LOCK_ALREADY_ACQUIRED); 434 | 435 | if (ret) { 436 | printk (KERN_ERR "%s: Failed to send data\n", __func__); 437 | sdio_release_host(context->func); 438 | return ret; 439 | } 440 | /* printk (KERN_ERR "--> %d %d %d\n", block_cnt, data_left, len_to_send);*/ 441 | 442 | data_left -= len_to_send; 443 | pos += len_to_send; 444 | } while (data_left); 445 | 446 | context->tx_buffer_count += buf_needed; 447 | context->tx_buffer_count = context->tx_buffer_count % ESP_TX_BUFFER_MAX; 448 | 449 | sdio_release_host(context->func); 450 | 451 | return 0; 452 | } 453 | 454 | static struct esp_sdio_context * init_sdio_func(struct sdio_func *func) 455 | { 456 | struct esp_sdio_context *context = NULL; 457 | int ret = 0; 458 | 459 | if (!func) 460 | return NULL; 461 | 462 | context = &sdio_context; 463 | 464 | context->func = func; 465 | 466 | sdio_claim_host(func); 467 | 468 | /* Enable Function */ 469 | ret = sdio_enable_func(func); 470 | if (ret) { 471 | return NULL; 472 | } 473 | 474 | /* Register IRQ */ 475 | ret = sdio_claim_irq(func, esp_handle_isr); 476 | if (ret) { 477 | sdio_disable_func(func); 478 | return NULL; 479 | } 480 | 481 | /* Set private data */ 482 | sdio_set_drvdata(func, context); 483 | 484 | context->state = ESP_CONTEXT_INIT; 485 | 486 | sdio_release_host(func); 487 | 488 | return context; 489 | } 490 | 491 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS 492 | static int monitor_process(void *data) 493 | { 494 | u32 val, intr, len_reg, rdata, old_len = 0; 495 | struct esp_sdio_context *context = (struct esp_sdio_context *) data; 496 | struct sk_buff *skb; 497 | 498 | while (!kthread_should_stop()) { 499 | msleep(5000); 500 | 501 | val = intr = len_reg = rdata = 0; 502 | 503 | esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG, 504 | (u8 *) &val, sizeof(val), ACQUIRE_LOCK); 505 | 506 | len_reg = val & ESP_SLAVE_LEN_MASK; 507 | 508 | val = 0; 509 | esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) &val, 510 | sizeof(val), ACQUIRE_LOCK); 511 | 512 | rdata = ((val >> 16) & ESP_TX_BUFFER_MASK); 513 | 514 | esp_read_reg(context, ESP_SLAVE_INT_ST_REG, 515 | (u8 *) &intr, sizeof(intr), ACQUIRE_LOCK); 516 | 517 | 518 | if (len_reg > context->rx_byte_count) { 519 | if (old_len && (context->rx_byte_count == old_len)) { 520 | printk (KERN_DEBUG "Monitor thread ----> [%d - %d] [%d - %d] %d\n", 521 | len_reg, context->rx_byte_count, 522 | rdata, context->tx_buffer_count, intr); 523 | 524 | skb = read_packet(context->adapter); 525 | 526 | if (!skb) 527 | continue; 528 | 529 | if (skb->len) 530 | printk (KERN_DEBUG "%s: Flushed %d bytes\n", __func__, skb->len); 531 | 532 | /* drop the packet */ 533 | dev_kfree_skb(skb); 534 | } 535 | } 536 | 537 | old_len = context->rx_byte_count; 538 | } 539 | 540 | do_exit(0); 541 | return 0; 542 | } 543 | #endif 544 | 545 | static int esp_probe(struct sdio_func *func, 546 | const struct sdio_device_id *id) 547 | { 548 | struct esp_sdio_context *context = NULL; 549 | int ret = 0; 550 | uint32_t cap = 0; 551 | 552 | if (func->num != 1) { 553 | return -EINVAL; 554 | } 555 | 556 | printk(KERN_INFO "%s: ESP network device detected\n", __func__); 557 | 558 | context = init_sdio_func(func); 559 | 560 | if (!context) { 561 | return -ENOMEM; 562 | } 563 | 564 | generate_slave_intr(context, BIT(ESP_RESET)); 565 | 566 | msleep(200); 567 | 568 | ret = init_context(context); 569 | if (ret) { 570 | deinit_sdio_func(func); 571 | return ret; 572 | } 573 | 574 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 575 | ret = esp_serial_init((void *) context->adapter); 576 | if (ret != 0) { 577 | esp_remove(func); 578 | printk(KERN_ERR "Error initialising serial interface\n"); 579 | return ret; 580 | } 581 | #endif 582 | 583 | ret = esp_add_card(context->adapter); 584 | if (ret) { 585 | esp_remove(func); 586 | printk (KERN_ERR "Failed to add card\n"); 587 | deinit_sdio_func(func); 588 | return ret; 589 | } 590 | 591 | /* Read slave capabilities */ 592 | esp_read_reg(context, ESP_SLAVE_SCRATCH_REG_0, 593 | (u8 *) &cap, sizeof(cap), ACQUIRE_LOCK); 594 | 595 | context->adapter->capabilities = cap; 596 | 597 | print_capabilities(cap); 598 | 599 | if (esp_is_bt_supported_over_sdio(cap)) { 600 | ret = esp_init_bt(context->adapter); 601 | if (ret) { 602 | esp_remove(func); 603 | printk (KERN_ERR "Failed to init BT\n"); 604 | deinit_sdio_func(func); 605 | return ret; 606 | } 607 | } 608 | 609 | context->state = ESP_CONTEXT_READY; 610 | 611 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS 612 | monitor_thread = kthread_run(monitor_process, context, "Monitor process"); 613 | 614 | if (!monitor_thread) 615 | printk (KERN_ERR "Failed to create monitor thread\n"); 616 | #endif 617 | 618 | 619 | msleep(200); 620 | generate_slave_intr(context, BIT(ESP_OPEN_DATA_PATH)); 621 | return ret; 622 | } 623 | 624 | /* SDIO driver structure to be registered with kernel */ 625 | static struct sdio_driver esp_sdio_driver = { 626 | .name = "esp_sdio", 627 | .id_table = esp_devices, 628 | .probe = esp_probe, 629 | .remove = esp_remove, 630 | }; 631 | 632 | int esp_init_interface_layer(struct esp_adapter *adapter) 633 | { 634 | if (!adapter) 635 | return -EINVAL; 636 | 637 | adapter->if_context = &sdio_context; 638 | adapter->if_ops = &if_ops; 639 | sdio_context.adapter = adapter; 640 | 641 | return sdio_register_driver(&esp_sdio_driver); 642 | } 643 | 644 | void esp_deinit_interface_layer(void) 645 | { 646 | sdio_unregister_driver(&esp_sdio_driver); 647 | } 648 | -------------------------------------------------------------------------------- /sdio/esp_sdio_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "esp_sdio_api.h" 26 | 27 | static int esp_read_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u8 is_lock_needed) 28 | { 29 | struct sdio_func *func = NULL; 30 | int ret; 31 | 32 | if (!context || !context->func || !data) { 33 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__); 34 | return -1; 35 | } 36 | 37 | func = context->func; 38 | 39 | if (is_lock_needed) 40 | sdio_claim_host(func); 41 | 42 | *data = sdio_readb(func, reg, &ret); 43 | 44 | if (is_lock_needed) 45 | sdio_release_host(func); 46 | 47 | return ret; 48 | } 49 | 50 | static int esp_write_byte(struct esp_sdio_context *context, u32 reg, u8 data, u8 is_lock_needed) 51 | { 52 | struct sdio_func *func = NULL; 53 | int ret; 54 | 55 | if (!context || !context->func) { 56 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__); 57 | return -1; 58 | } 59 | 60 | func = context->func; 61 | 62 | if (is_lock_needed) 63 | sdio_claim_host(func); 64 | 65 | sdio_writeb(func, data, reg, &ret); 66 | 67 | if (is_lock_needed) 68 | sdio_release_host(func); 69 | 70 | return ret; 71 | } 72 | 73 | static int esp_read_multi_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 74 | { 75 | struct sdio_func *func = NULL; 76 | int ret; 77 | 78 | if (!context || !context->func || !data) { 79 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__); 80 | return -1; 81 | } 82 | 83 | func = context->func; 84 | 85 | if (is_lock_needed) 86 | sdio_claim_host(func); 87 | 88 | ret = sdio_memcpy_fromio(func, data, reg, size); 89 | 90 | if (is_lock_needed) 91 | sdio_release_host(func); 92 | 93 | return ret; 94 | } 95 | 96 | static int esp_write_multi_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 97 | { 98 | struct sdio_func *func = NULL; 99 | int ret; 100 | 101 | if (!context || !context->func || !data) { 102 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__); 103 | return -1; 104 | } 105 | 106 | func = context->func; 107 | 108 | if (is_lock_needed) 109 | sdio_claim_host(func); 110 | 111 | ret = sdio_memcpy_toio(func, reg, data, size); 112 | 113 | if (is_lock_needed) 114 | sdio_release_host(func); 115 | 116 | return ret; 117 | } 118 | 119 | int esp_read_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 120 | { 121 | /* Need to apply address mask when reading/writing slave registers */ 122 | reg &= ESP_ADDRESS_MASK; 123 | 124 | if (size <= 1) { 125 | return esp_read_byte(context, reg, data, is_lock_needed); 126 | } else { 127 | return esp_read_multi_byte(context, reg, data, size, is_lock_needed); 128 | } 129 | } 130 | 131 | int esp_read_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 132 | { 133 | if (size <= 1) { 134 | return esp_read_byte(context, reg, data, is_lock_needed); 135 | } else { 136 | return esp_read_multi_byte(context, reg, data, size, is_lock_needed); 137 | } 138 | } 139 | 140 | int esp_write_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 141 | { 142 | /* Need to apply address mask when reading/writing slave registers */ 143 | reg &= ESP_ADDRESS_MASK; 144 | 145 | if (size <= 1) { 146 | return esp_write_byte(context, reg, *data, is_lock_needed); 147 | } else { 148 | return esp_write_multi_byte(context, reg, data, size, is_lock_needed); 149 | } 150 | } 151 | 152 | int esp_write_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed) 153 | { 154 | if (size <= 1) { 155 | return esp_write_byte(context, reg, *data, is_lock_needed); 156 | } else { 157 | return esp_write_multi_byte(context, reg, data, size, is_lock_needed); 158 | } 159 | } 160 | 161 | -------------------------------------------------------------------------------- /sdio/esp_sdio_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef _ESP_SDIO_API_H_ 21 | #define _ESP_SDIO_API_H_ 22 | #include "esp_sdio_decl.h" 23 | 24 | int esp_read_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed); 25 | int esp_read_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed); 26 | int esp_write_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed); 27 | int esp_write_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /sdio/esp_sdio_decl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Espressif Systems Wireless LAN device driver 3 | * 4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 8 | * (the "License"). You may use, redistribute and/or modify this File in 9 | * accordance with the terms and conditions of the License, a copy of which 10 | * is available by writing to the Free Software Foundation, Inc., 11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 | * 14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 | * this warranty disclaimer. 18 | */ 19 | 20 | #ifndef _ESP_DECL_H_ 21 | #define _ESP_DECL_H_ 22 | 23 | #include "esp.h" 24 | 25 | /* Interrupt Status */ 26 | #define ESP_SLAVE_BIT0_INT BIT(0) 27 | #define ESP_SLAVE_BIT1_INT BIT(1) 28 | #define ESP_SLAVE_BIT2_INT BIT(2) 29 | #define ESP_SLAVE_BIT3_INT BIT(3) 30 | #define ESP_SLAVE_BIT4_INT BIT(4) 31 | #define ESP_SLAVE_BIT5_INT BIT(5) 32 | #define ESP_SLAVE_BIT6_INT BIT(6) 33 | #define ESP_SLAVE_BIT7_INT BIT(7) 34 | #define ESP_SLAVE_RX_UNDERFLOW_INT BIT(16) 35 | #define ESP_SLAVE_TX_OVERFLOW_INT BIT(17) 36 | #define ESP_SLAVE_RX_NEW_PACKET_INT BIT(23) 37 | 38 | 39 | #define ESP_SLAVE_CMD53_END_ADDR 0x1F800 40 | #define ESP_SLAVE_LEN_MASK 0xFFFFF 41 | #define ESP_BLOCK_SIZE 512 42 | #define ESP_RX_BYTE_MAX 0x100000 43 | #define ESP_RX_BUFFER_SIZE 2048 44 | 45 | #define ESP_TX_BUFFER_MASK 0xFFF 46 | #define ESP_TX_BUFFER_MAX 0x1000 47 | #define ESP_MAX_BUF_CNT 10 48 | 49 | #define ESP_SLAVE_SLCHOST_BASE 0x3FF55000 50 | 51 | #define ESP_SLAVE_SCRATCH_REG_7 (ESP_SLAVE_SLCHOST_BASE + 0x8C) 52 | /* SLAVE registers */ 53 | /* Interrupt Registers */ 54 | #define ESP_SLAVE_INT_RAW_REG (ESP_SLAVE_SLCHOST_BASE + 0x50) 55 | #define ESP_SLAVE_INT_ST_REG (ESP_SLAVE_SLCHOST_BASE + 0x58) 56 | #define ESP_SLAVE_INT_CLR_REG (ESP_SLAVE_SLCHOST_BASE + 0xD4) 57 | 58 | /* Data path registers*/ 59 | #define ESP_SLAVE_PACKET_LEN_REG (ESP_SLAVE_SLCHOST_BASE + 0x60) 60 | #define ESP_SLAVE_TOKEN_RDATA (ESP_SLAVE_SLCHOST_BASE + 0x44) 61 | 62 | /* Scratch registers*/ 63 | #define ESP_SLAVE_SCRATCH_REG_0 (ESP_SLAVE_SLCHOST_BASE + 0x6C) 64 | #define ESP_SLAVE_SCRATCH_REG_1 (ESP_SLAVE_SLCHOST_BASE + 0x70) 65 | #define ESP_SLAVE_SCRATCH_REG_2 (ESP_SLAVE_SLCHOST_BASE + 0x74) 66 | #define ESP_SLAVE_SCRATCH_REG_3 (ESP_SLAVE_SLCHOST_BASE + 0x78) 67 | #define ESP_SLAVE_SCRATCH_REG_4 (ESP_SLAVE_SLCHOST_BASE + 0x7C) 68 | #define ESP_SLAVE_SCRATCH_REG_6 (ESP_SLAVE_SLCHOST_BASE + 0x88) 69 | #define ESP_SLAVE_SCRATCH_REG_8 (ESP_SLAVE_SLCHOST_BASE + 0x9C) 70 | #define ESP_SLAVE_SCRATCH_REG_9 (ESP_SLAVE_SLCHOST_BASE + 0xA0) 71 | #define ESP_SLAVE_SCRATCH_REG_10 (ESP_SLAVE_SLCHOST_BASE + 0xA4) 72 | #define ESP_SLAVE_SCRATCH_REG_11 (ESP_SLAVE_SLCHOST_BASE + 0xA8) 73 | #define ESP_SLAVE_SCRATCH_REG_12 (ESP_SLAVE_SLCHOST_BASE + 0xAC) 74 | #define ESP_SLAVE_SCRATCH_REG_13 (ESP_SLAVE_SLCHOST_BASE + 0xB0) 75 | #define ESP_SLAVE_SCRATCH_REG_14 (ESP_SLAVE_SLCHOST_BASE + 0xB4) 76 | #define ESP_SLAVE_SCRATCH_REG_15 (ESP_SLAVE_SLCHOST_BASE + 0xB8) 77 | 78 | #define ESP_ADDRESS_MASK 0x3FF 79 | 80 | #define ESP_VENDOR_ID 0x6666 81 | #define ESP_DEVICE_ID_1 0x2222 82 | #define ESP_DEVICE_ID_2 0x3333 83 | 84 | 85 | enum context_state { 86 | ESP_CONTEXT_DISABLED = 0, 87 | ESP_CONTEXT_INIT, 88 | ESP_CONTEXT_READY 89 | }; 90 | 91 | struct esp_sdio_context { 92 | struct esp_adapter *adapter; 93 | struct sdio_func *func; 94 | enum context_state state; 95 | u32 rx_byte_count; 96 | u32 tx_buffer_count; 97 | }; 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /spi/esp_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 3 | * 4 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 5 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 6 | * (the "License"). You may use, redistribute and/or modify this File in 7 | * accordance with the terms and conditions of the License, a copy of which 8 | * is available by writing to the Free Software Foundation, Inc., 9 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 10 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 11 | * 12 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 13 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 14 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 15 | * this warranty disclaimer. 16 | */ 17 | #include 18 | #include 19 | #include 20 | #include "esp_spi.h" 21 | #include "esp_if.h" 22 | #include "esp_api.h" 23 | #include "esp_bt_api.h" 24 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 25 | #include "esp_serial.h" 26 | #endif 27 | 28 | static struct sk_buff * read_packet(struct esp_adapter *adapter); 29 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size); 30 | static void spi_exit(struct esp_spi_context *esp); 31 | 32 | volatile u8 data_path = 0; 33 | 34 | static struct esp_if_ops if_ops = { 35 | .read = read_packet, 36 | .write = write_packet, 37 | }; 38 | 39 | 40 | static void open_data_path(void) 41 | { 42 | msleep(200); 43 | data_path = OPEN_DATAPATH; 44 | } 45 | 46 | static void close_data_path(void) 47 | { 48 | data_path = CLOSE_DATAPATH; 49 | msleep(200); 50 | } 51 | 52 | static irqreturn_t spi_interrupt_handler(int irq, void * priv) 53 | { 54 | struct esp_spi_context *esp = (struct esp_spi_context *)priv; 55 | 56 | /* ESP32 is ready for next transaction */ 57 | if (esp->spi_workqueue) 58 | queue_work(esp->spi_workqueue, &esp->spi_work); 59 | 60 | return IRQ_HANDLED; 61 | } 62 | 63 | static struct sk_buff * read_packet(struct esp_adapter *adapter) 64 | { 65 | struct esp_spi_context *esp; 66 | struct sk_buff *skb = NULL; 67 | 68 | if (!data_path) { 69 | return NULL; 70 | } 71 | 72 | if (!adapter || !adapter->if_context) { 73 | printk (KERN_ERR "%s: Invalid args\n", __func__); 74 | return NULL; 75 | } 76 | 77 | esp = adapter->if_context; 78 | 79 | if (esp->esp_spi_dev) { 80 | skb = skb_dequeue(&(esp->rx_q)); 81 | } else { 82 | printk (KERN_ERR "%s: Invalid args\n", __func__); 83 | return NULL; 84 | } 85 | 86 | return skb; 87 | } 88 | 89 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size) 90 | { 91 | struct esp_spi_context *esp; 92 | struct sk_buff *skb; 93 | u8 *tx_buf = NULL; 94 | 95 | if (!adapter || !adapter->if_context || !buf || !size || (size > SPI_BUF_SIZE)) { 96 | printk (KERN_ERR "%s: Invalid args\n", __func__); 97 | return -EINVAL; 98 | } 99 | 100 | if (!data_path) { 101 | return -EPERM; 102 | } 103 | 104 | /* Adjust length to make it multiple of 4 bytes */ 105 | size += 4 - (size & 3); 106 | 107 | esp = adapter->if_context; 108 | 109 | skb = esp_alloc_skb(size); 110 | 111 | if (!skb) 112 | return -ENOMEM; 113 | 114 | tx_buf = skb_put(skb, size); 115 | 116 | if (!tx_buf) { 117 | dev_kfree_skb(skb); 118 | return -ENOMEM; 119 | } 120 | 121 | /* TODO: This memecpy can be avoided if this function receives SKB as an argument */ 122 | memcpy(tx_buf, buf, size); 123 | 124 | /* Enqueue SKB in tx_q */ 125 | skb_queue_tail(&esp->tx_q, skb); 126 | 127 | return 0; 128 | } 129 | 130 | static void process_capabilities(struct esp_spi_context *esp, u8 cap) 131 | { 132 | printk (KERN_INFO "ESP32 capabilities: 0x%x", cap); 133 | 134 | /* Reset BT */ 135 | esp_deinit_bt(esp->adapter); 136 | 137 | if ((cap & ESP_BT_SPI_SUPPORT) || (cap & ESP_BT_SDIO_SUPPORT)) { 138 | msleep(200); 139 | esp_init_bt(esp->adapter); 140 | } 141 | } 142 | 143 | static void process_init_event(struct esp_spi_context *esp, u8 *evt_buf, u8 len) 144 | { 145 | u8 len_left = len, tag_len; 146 | u8 *pos; 147 | 148 | if (!evt_buf) 149 | return; 150 | 151 | pos = evt_buf; 152 | 153 | while (len_left) { 154 | tag_len = *(pos + 1); 155 | if (*pos == ESP_PRIV_CAPABILITY) { 156 | process_capabilities(esp, *(pos + 2)); 157 | } else { 158 | printk (KERN_WARNING "Unsupported tag in event"); 159 | } 160 | len_left = len_left - (tag_len + 2); 161 | } 162 | } 163 | 164 | static void process_event(struct esp_spi_context *esp, u8 *evt_buf, u16 len) 165 | { 166 | struct esp_priv_event *event; 167 | 168 | if (!evt_buf || !len) 169 | return; 170 | 171 | event = (struct esp_priv_event *) evt_buf; 172 | 173 | if (event->event_type == ESP_PRIV_EVENT_INIT) { 174 | printk (KERN_INFO "Received INIT event from esp32"); 175 | process_init_event(esp, event->event_data, event->event_len); 176 | } else { 177 | printk (KERN_WARNING "Drop unknown event"); 178 | } 179 | } 180 | 181 | static void process_priv_communication(struct esp_spi_context *esp, struct sk_buff *skb) 182 | { 183 | struct esp_payload_header *header; 184 | u8 *payload; 185 | u16 len; 186 | 187 | if (!skb || !skb->data) 188 | return; 189 | 190 | header = (struct esp_payload_header *) skb->data; 191 | 192 | payload = skb->data + le16_to_cpu(header->offset); 193 | len = le16_to_cpu(header->len); 194 | 195 | if (header->priv_pkt_type == ESP_PACKET_TYPE_EVENT) { 196 | process_event(esp, payload, len); 197 | } 198 | 199 | dev_kfree_skb(skb); 200 | } 201 | 202 | static int process_rx_buf(struct esp_spi_context *esp, struct sk_buff *skb) 203 | { 204 | struct esp_payload_header *header; 205 | u16 len = 0; 206 | u16 offset = 0; 207 | 208 | if (!skb) 209 | return -EINVAL; 210 | 211 | header = (struct esp_payload_header *) skb->data; 212 | 213 | offset = le16_to_cpu(header->offset); 214 | 215 | /* Validate received SKB. Check len and offset fields */ 216 | if (offset != sizeof(struct esp_payload_header)) 217 | return -EINVAL; 218 | 219 | len = le16_to_cpu(header->len); 220 | if (!len) 221 | return -EINVAL; 222 | 223 | len += sizeof(struct esp_payload_header); 224 | 225 | if (len > SPI_BUF_SIZE) 226 | return -EINVAL; 227 | 228 | /* Trim SKB to actual size */ 229 | skb_trim(skb, len); 230 | 231 | if (header->if_type == ESP_PRIV_IF) { 232 | process_priv_communication(esp, skb); 233 | return 0; 234 | } 235 | 236 | if (!data_path) 237 | return -EPERM; 238 | 239 | /* enqueue skb for read_packet to pick it */ 240 | skb_queue_tail(&esp->rx_q, skb); 241 | 242 | /* indicate reception of new packet */ 243 | esp_process_new_packet_intr(esp->adapter); 244 | 245 | return 0; 246 | } 247 | 248 | static void esp_spi_work(struct work_struct *work) 249 | { 250 | struct esp_spi_context *esp = container_of(work, 251 | struct esp_spi_context, spi_work); 252 | struct spi_transfer trans; 253 | struct sk_buff *tx_skb, *rx_skb; 254 | u8 *rx_buf; 255 | int ret = 0; 256 | 257 | memset(&trans, 0, sizeof(trans)); 258 | tx_skb = NULL; 259 | 260 | /* Setup and execute SPI transaction 261 | * Tx_buf: Check if tx_q has valid buffer for transmission, 262 | * else keep it blank 263 | * 264 | * Rx_buf: Allocate memory for incoming data. This will be freed 265 | * immediately if received buffer is invalid. 266 | * If it is a valid buffer, upper layer will free it. 267 | * */ 268 | 269 | /* Configure TX buffer if available */ 270 | if (data_path) 271 | tx_skb = skb_dequeue(&esp->tx_q); 272 | 273 | if (tx_skb) { 274 | trans.tx_buf = tx_skb->data; 275 | } 276 | 277 | /* Configure RX buffer */ 278 | rx_skb = esp_alloc_skb(SPI_BUF_SIZE); 279 | rx_buf = skb_put(rx_skb, SPI_BUF_SIZE); 280 | 281 | memset(rx_buf, 0, SPI_BUF_SIZE); 282 | 283 | trans.rx_buf = rx_buf; 284 | trans.len = SPI_BUF_SIZE; 285 | 286 | ret = spi_sync_transfer(esp->esp_spi_dev, &trans, 1); 287 | 288 | if (ret) { 289 | printk(KERN_ERR "SPI Transaction failed: %d", ret); 290 | } 291 | 292 | /* Free rx_skb if received data is not valid */ 293 | if (process_rx_buf(esp, rx_skb)) { 294 | dev_kfree_skb(rx_skb); 295 | } 296 | 297 | if (tx_skb) 298 | dev_kfree_skb(tx_skb); 299 | } 300 | 301 | static int spi_init(struct esp_spi_context *esp, struct spi_device *spi) 302 | { 303 | struct device *dev = &spi->dev; 304 | int status = 0; 305 | 306 | esp->spi_workqueue = create_workqueue("ESP_SPI_WORK_QUEUE"); 307 | if (!esp->spi_workqueue) { 308 | spi_exit(esp); 309 | return -EFAULT; 310 | } 311 | 312 | INIT_WORK(&esp->spi_work, esp_spi_work); 313 | 314 | skb_queue_head_init(&esp->tx_q); 315 | skb_queue_head_init(&esp->rx_q); 316 | 317 | esp->esp_spi_dev = spi; 318 | if (!esp->esp_spi_dev) { 319 | dev_err(dev, "Failed to add new SPI device\n"); 320 | spi_exit(esp); 321 | return -ENODEV; 322 | } 323 | 324 | status = devm_request_irq(dev, spi->irq, spi_interrupt_handler, 325 | IRQF_SHARED | IRQF_TRIGGER_RISING, 326 | "esp_spi", esp); 327 | if (status) { 328 | dev_err(dev, "Failed to request IRQ %d\n", status); 329 | spi_exit(esp); 330 | return status; 331 | } 332 | 333 | open_data_path(); 334 | 335 | #ifdef CONFIG_SUPPORT_ESP_SERIAL 336 | status = esp_serial_init((void *) esp->adapter); 337 | if (status != 0) { 338 | spi_exit(esp); 339 | dev_err(dev, "Error initialising serial interface\n"); 340 | return status; 341 | } 342 | #endif 343 | 344 | status = esp_add_card(esp->adapter); 345 | if (status) { 346 | spi_exit(esp); 347 | dev_err(dev, "Failed to add card\n"); 348 | return status; 349 | } 350 | 351 | msleep(200); 352 | 353 | return status; 354 | } 355 | 356 | static void spi_exit(struct esp_spi_context *esp) 357 | { 358 | close_data_path(); 359 | msleep(200); 360 | 361 | skb_queue_purge(&esp->tx_q); 362 | skb_queue_purge(&esp->rx_q); 363 | 364 | if (esp->spi_workqueue) { 365 | destroy_workqueue(esp->spi_workqueue); 366 | esp->spi_workqueue = NULL; 367 | } 368 | 369 | esp_serial_cleanup(); 370 | esp_remove_card(esp->adapter); 371 | 372 | if (esp->adapter->hcidev) 373 | esp_deinit_bt(esp->adapter); 374 | 375 | memset(esp, 0, sizeof(*esp)); 376 | } 377 | 378 | static int esp_init_interface_layer(struct esp_spi_context *esp, struct esp_adapter *adapter, 379 | struct spi_device *spi) 380 | { 381 | if (!adapter) 382 | return -EINVAL; 383 | 384 | memset(esp, 0, sizeof(*esp)); 385 | 386 | adapter->if_context = esp; 387 | adapter->if_ops = &if_ops; 388 | adapter->if_type = ESP_IF_TYPE_SPI; 389 | esp->adapter = adapter; 390 | 391 | return spi_init(esp, spi); 392 | } 393 | 394 | static void esp_deinit_interface_layer(struct esp_spi_context *esp) 395 | { 396 | spi_exit(esp); 397 | } 398 | 399 | static void esp32_spi_reset(struct esp_spi_context *esp) 400 | { 401 | gpiod_direction_output(esp->reset_gpio, GPIOD_OUT_LOW); 402 | udelay(100); 403 | gpiod_direction_output(esp->reset_gpio, GPIOD_OUT_HIGH); 404 | } 405 | 406 | static int esp32_spi_probe(struct spi_device *spi) 407 | { 408 | struct esp_spi_context *esp; 409 | int ret = 0; 410 | struct device *dev = &spi->dev; 411 | struct esp_adapter *adapter; 412 | 413 | esp = devm_kzalloc(dev, sizeof(*esp), GFP_KERNEL); 414 | if (!esp) 415 | return -ENOMEM; 416 | esp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 417 | if (IS_ERR(esp->reset_gpio)) { 418 | dev_err(dev, "Can't get reset gpio\n"); 419 | return -ENODEV; 420 | } 421 | spi_set_drvdata(spi, esp); 422 | 423 | esp32_spi_reset(esp); 424 | 425 | /* Init adapter */ 426 | adapter = init_adapter(); 427 | if (!adapter) 428 | return -EFAULT; 429 | 430 | /* Init transport layer */ 431 | ret = esp_init_interface_layer(esp, adapter, spi); 432 | if (ret != 0) { 433 | deinit_adapter(); 434 | } else 435 | dev_info(&spi->dev, "probed!\n"); 436 | 437 | return ret; 438 | } 439 | 440 | static int esp32_spi_remove(struct spi_device *spi) 441 | { 442 | struct esp_spi_context *esp = spi_get_drvdata(spi); 443 | 444 | esp_deinit_interface_layer(esp); 445 | deinit_adapter(); 446 | 447 | return 0; 448 | } 449 | 450 | #ifdef CONFIG_OF 451 | static const struct of_device_id esp32_spi_dt_ids[] = { 452 | { .compatible = "espressif,esp32" }, 453 | {}, 454 | }; 455 | MODULE_DEVICE_TABLE(of, esp32_spi_dt_ids); 456 | #endif 457 | 458 | static struct spi_driver esp32_spi_driver = { 459 | .driver = { 460 | .name = "esp32", 461 | .of_match_table = of_match_ptr(esp32_spi_dt_ids), 462 | }, 463 | .probe = esp32_spi_probe, 464 | .remove = esp32_spi_remove, 465 | }; 466 | module_spi_driver(esp32_spi_driver); 467 | 468 | MODULE_AUTHOR("Amey Inamdar "); 469 | MODULE_AUTHOR("Mangesh Malusare "); 470 | MODULE_AUTHOR("Yogesh Mantri "); 471 | MODULE_AUTHOR("Boundary Devices "); 472 | MODULE_DESCRIPTION("Host SPI driver for ESP32 Hosted solution"); 473 | MODULE_LICENSE("GPL"); 474 | MODULE_ALIAS("spi:esp32"); 475 | -------------------------------------------------------------------------------- /spi/esp_spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD 3 | * 4 | * This software file (the "File") is distributed by Espressif Systems (Shanghai) 5 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991 6 | * (the "License"). You may use, redistribute and/or modify this File in 7 | * accordance with the terms and conditions of the License, a copy of which 8 | * is available by writing to the Free Software Foundation, Inc., 9 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 10 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 11 | * 12 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 13 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 14 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 15 | * this warranty disclaimer. 16 | */ 17 | #ifndef _ESP_SPI_H_ 18 | #define _ESP_SPI_H_ 19 | 20 | #include "esp.h" 21 | 22 | #define SPI_BUF_SIZE 2048 23 | 24 | struct esp_spi_context { 25 | struct esp_adapter *adapter; 26 | struct spi_device *esp_spi_dev; 27 | struct sk_buff_head tx_q; 28 | struct sk_buff_head rx_q; 29 | struct workqueue_struct *spi_workqueue; 30 | struct work_struct spi_work; 31 | struct gpio_desc *reset_gpio; 32 | }; 33 | 34 | enum { 35 | CLOSE_DATAPATH, 36 | OPEN_DATAPATH, 37 | }; 38 | 39 | #endif 40 | --------------------------------------------------------------------------------