├── .gitattributes
├── .gitignore
├── AndroidManifest.xml
├── COPYING
├── README.md
├── project.properties
├── res
└── xml
│ └── device_filter.xml
└── src
└── com
├── hoho
└── android
│ └── usbserial
│ ├── driver
│ ├── CdcAcmSerialDriver.java
│ ├── CommonUsbSerialPort.java
│ ├── Cp21xxSerialDriver.java
│ ├── FtdiSerialDriver.java
│ ├── ProbeTable.java
│ ├── ProlificSerialDriver.java
│ ├── UsbId.java
│ ├── UsbSerialDriver.java
│ ├── UsbSerialPort.java
│ ├── UsbSerialProber.java
│ └── UsbSerialRuntimeException.java
│ └── util
│ ├── HexDump.java
│ └── SerialInputOutputManager.java
└── rtlsdr
└── android
├── SdrSerialDriver.java
├── SdrSerialDriverOrig.java
├── SdrUsbId.java
└── tuners
├── E4K.java
├── FC0012.java
├── FC0013.java
├── FC2580.java
├── IRtlSdrTuner.java
└── R820T.java
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | gen/
10 | tmp/
11 | *.tmp
12 | *.bak
13 | *.swp
14 | *~.nib
15 | local.properties
16 | .classpath
17 | .settings/
18 | .loadpath
19 |
20 | # External tool builders
21 | .externalToolBuilders/
22 |
23 | # Locally stored "Eclipse launch configurations"
24 | *.launch
25 |
26 | # CDT-specific
27 | .cproject
28 |
29 | # PDT-specific
30 | .buildpath
31 |
32 |
33 | #################
34 | ## Visual Studio
35 | #################
36 |
37 | ## Ignore Visual Studio temporary files, build results, and
38 | ## files generated by popular Visual Studio add-ons.
39 |
40 | # User-specific files
41 | *.suo
42 | *.user
43 | *.sln.docstates
44 |
45 | # Build results
46 |
47 | [Dd]ebug/
48 | [Rr]elease/
49 | x64/
50 | build/
51 | [Bb]in/
52 | [Oo]bj/
53 |
54 | # MSTest test Results
55 | [Tt]est[Rr]esult*/
56 | [Bb]uild[Ll]og.*
57 |
58 | *_i.c
59 | *_p.c
60 | *.ilk
61 | *.meta
62 | *.obj
63 | *.pch
64 | *.pdb
65 | *.pgc
66 | *.pgd
67 | *.rsp
68 | *.sbr
69 | *.tlb
70 | *.tli
71 | *.tlh
72 | *.tmp
73 | *.tmp_proj
74 | *.log
75 | *.vspscc
76 | *.vssscc
77 | .builds
78 | *.pidb
79 | *.log
80 | *.scc
81 |
82 | # Visual C++ cache files
83 | ipch/
84 | *.aps
85 | *.ncb
86 | *.opensdf
87 | *.sdf
88 | *.cachefile
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 |
102 | # TeamCity is a build add-in
103 | _TeamCity*
104 |
105 | # DotCover is a Code Coverage Tool
106 | *.dotCover
107 |
108 | # NCrunch
109 | *.ncrunch*
110 | .*crunch*.local.xml
111 |
112 | # Installshield output folder
113 | [Ee]xpress/
114 |
115 | # DocProject is a documentation generator add-in
116 | DocProject/buildhelp/
117 | DocProject/Help/*.HxT
118 | DocProject/Help/*.HxC
119 | DocProject/Help/*.hhc
120 | DocProject/Help/*.hhk
121 | DocProject/Help/*.hhp
122 | DocProject/Help/Html2
123 | DocProject/Help/html
124 |
125 | # Click-Once directory
126 | publish/
127 |
128 | # Publish Web Output
129 | *.Publish.xml
130 | *.pubxml
131 |
132 | # NuGet Packages Directory
133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
134 | #packages/
135 |
136 | # Windows Azure Build Output
137 | csx
138 | *.build.csdef
139 |
140 | # Windows Store app package directory
141 | AppPackages/
142 |
143 | # Others
144 | sql/
145 | *.Cache
146 | ClientBin/
147 | [Ss]tyle[Cc]op.*
148 | ~$*
149 | *~
150 | *.dbmdl
151 | *.[Pp]ublish.xml
152 | *.pfx
153 | *.publishsettings
154 |
155 | # RIA/Silverlight projects
156 | Generated_Code/
157 |
158 | # Backup & report files from converting an old project file to a newer
159 | # Visual Studio version. Backup files are not needed, because we have git ;-)
160 | _UpgradeReport_Files/
161 | Backup*/
162 | UpgradeLog*.XML
163 | UpgradeLog*.htm
164 |
165 | # SQL Server files
166 | App_Data/*.mdf
167 | App_Data/*.ldf
168 |
169 | #############
170 | ## Windows detritus
171 | #############
172 |
173 | # Windows image file caches
174 | Thumbs.db
175 | ehthumbs.db
176 |
177 | # Folder config file
178 | Desktop.ini
179 |
180 | # Recycle Bin used on file shares
181 | $RECYCLE.BIN/
182 |
183 | # Mac crap
184 | .DS_Store
185 |
186 |
187 | #############
188 | ## Python
189 | #############
190 |
191 | *.py[co]
192 |
193 | # Packages
194 | *.egg
195 | *.egg-info
196 | dist/
197 | build/
198 | eggs/
199 | parts/
200 | var/
201 | sdist/
202 | develop-eggs/
203 | .installed.cfg
204 |
205 | # Installer logs
206 | pip-log.txt
207 |
208 | # Unit test / coverage reports
209 | .coverage
210 | .tox
211 |
212 | #Translations
213 | *.mo
214 |
215 | #Mr Developer
216 | .mr.developer.cfg
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 51 Franklin Street, 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 Library 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 |
294 | Copyright (C) 19yy
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
307 | along with this program; if not, write to the Free Software
308 | Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
309 |
310 |
311 | Also add information on how to contact you by electronic and paper mail.
312 |
313 | If the program is interactive, make it output a short notice like this
314 | when it starts in an interactive mode:
315 |
316 | Gnomovision version 69, Copyright (C) 19yy name of author
317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 | This is free software, and you are welcome to redistribute it
319 | under certain conditions; type `show c' for details.
320 |
321 | The hypothetical commands `show w' and `show c' should show the appropriate
322 | parts of the General Public License. Of course, the commands you use may
323 | be called something other than `show w' and `show c'; they could even be
324 | mouse-clicks or menu items--whatever suits your program.
325 |
326 | You should also get your employer (if you work as a programmer) or your
327 | school, if any, to sign a "copyright disclaimer" for the program, if
328 | necessary. Here is a sample; alter the names:
329 |
330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
332 |
333 | , 1 April 1989
334 | Ty Coon, President of Vice
335 |
336 | This General Public License does not permit incorporating your program into
337 | proprietary programs. If your program is a subroutine library, you may
338 | consider it more useful to permit linking proprietary applications with the
339 | library. If this is what you want to do, use the GNU Library General
340 | Public License instead of this License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | flightfeeder-android
2 | ====================
3 |
4 | FlightFeeder app for Android
5 |
6 | An Android app to send ADSB data back to FA. This app currently depends on the Avare ADSB Pro app to feed the ADSB frames over for decoding and conversion to ADEPT format before sending to FA.
7 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/res/xml/device_filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbConstants;
25 | import android.hardware.usb.UsbDevice;
26 | import android.hardware.usb.UsbDeviceConnection;
27 | import android.hardware.usb.UsbEndpoint;
28 | import android.hardware.usb.UsbInterface;
29 | import android.hardware.usb.UsbRequest;
30 | import android.os.Build;
31 | import android.util.Log;
32 |
33 | import java.io.IOException;
34 | import java.nio.ByteBuffer;
35 | import java.util.Collections;
36 | import java.util.LinkedHashMap;
37 | import java.util.List;
38 | import java.util.Map;
39 |
40 | /**
41 | * USB CDC/ACM serial driver implementation.
42 | *
43 | * @author mike wakerly (opensource@hoho.com)
44 | * @see Universal
46 | * Serial Bus Class Definitions for Communication Devices, v1.1
47 | */
48 | public class CdcAcmSerialDriver implements UsbSerialDriver {
49 |
50 | private final String TAG = CdcAcmSerialDriver.class.getSimpleName();
51 |
52 | private final UsbDevice mDevice;
53 | private final UsbSerialPort mPort;
54 |
55 | public CdcAcmSerialDriver(UsbDevice device) {
56 | mDevice = device;
57 | mPort = new CdcAcmSerialPort(device, 0);
58 | }
59 |
60 | @Override
61 | public UsbDevice getDevice() {
62 | return mDevice;
63 | }
64 |
65 | @Override
66 | public List getPorts() {
67 | return Collections.singletonList(mPort);
68 | }
69 |
70 | class CdcAcmSerialPort extends CommonUsbSerialPort {
71 |
72 | private final boolean mEnableAsyncReads;
73 | private UsbInterface mControlInterface;
74 | private UsbInterface mDataInterface;
75 |
76 | private UsbEndpoint mControlEndpoint;
77 | private UsbEndpoint mReadEndpoint;
78 | private UsbEndpoint mWriteEndpoint;
79 |
80 | private boolean mRts = false;
81 | private boolean mDtr = false;
82 |
83 | private static final int USB_RECIP_INTERFACE = 0x01;
84 | private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
85 |
86 | private static final int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2
87 | private static final int GET_LINE_CODING = 0x21;
88 | private static final int SET_CONTROL_LINE_STATE = 0x22;
89 | private static final int SEND_BREAK = 0x23;
90 |
91 | public CdcAcmSerialPort(UsbDevice device, int portNumber) {
92 | super(device, portNumber);
93 | mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
94 | }
95 |
96 | @Override
97 | public UsbSerialDriver getDriver() {
98 | return CdcAcmSerialDriver.this;
99 | }
100 |
101 | @Override
102 | public void open(UsbDeviceConnection connection) throws IOException {
103 | if (mConnection != null) {
104 | throw new IOException("Already open");
105 | }
106 |
107 | mConnection = connection;
108 | boolean opened = false;
109 | try {
110 | Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
111 | mControlInterface = mDevice.getInterface(0);
112 | Log.d(TAG, "Control iface=" + mControlInterface);
113 | // class should be USB_CLASS_COMM
114 |
115 | if (!mConnection.claimInterface(mControlInterface, true)) {
116 | throw new IOException("Could not claim control interface.");
117 | }
118 | mControlEndpoint = mControlInterface.getEndpoint(0);
119 | Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection());
120 |
121 | Log.d(TAG, "Claiming data interface.");
122 | mDataInterface = mDevice.getInterface(1);
123 | Log.d(TAG, "data iface=" + mDataInterface);
124 | // class should be USB_CLASS_CDC_DATA
125 |
126 | if (!mConnection.claimInterface(mDataInterface, true)) {
127 | throw new IOException("Could not claim data interface.");
128 | }
129 | mReadEndpoint = mDataInterface.getEndpoint(1);
130 | Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection());
131 | mWriteEndpoint = mDataInterface.getEndpoint(0);
132 | Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection());
133 | if (mEnableAsyncReads) {
134 | Log.d(TAG, "Async reads enabled");
135 | } else {
136 | Log.d(TAG, "Async reads disabled.");
137 | }
138 | opened = true;
139 | } finally {
140 | if (!opened) {
141 | mConnection = null;
142 | }
143 | }
144 | }
145 |
146 | private int sendAcmControlMessage(int request, int value, byte[] buf) {
147 | return mConnection.controlTransfer(
148 | USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000);
149 | }
150 |
151 | @Override
152 | public void close() throws IOException {
153 | if (mConnection == null) {
154 | throw new IOException("Already closed");
155 | }
156 | mConnection.close();
157 | mConnection = null;
158 | }
159 |
160 | @Override
161 | public int read(byte[] dest, int timeoutMillis) throws IOException {
162 | if (mEnableAsyncReads) {
163 | final UsbRequest request = new UsbRequest();
164 | try {
165 | request.initialize(mConnection, mReadEndpoint);
166 | final ByteBuffer buf = ByteBuffer.wrap(dest);
167 | if (!request.queue(buf, dest.length)) {
168 | throw new IOException("Error queueing request.");
169 | }
170 |
171 | final UsbRequest response = mConnection.requestWait();
172 | if (response == null) {
173 | throw new IOException("Null response");
174 | }
175 |
176 | final int nread = buf.position();
177 | if (nread > 0) {
178 | //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
179 | return nread;
180 | } else {
181 | return 0;
182 | }
183 | } finally {
184 | request.close();
185 | }
186 | }
187 |
188 | final int numBytesRead;
189 | synchronized (mReadBufferLock) {
190 | int readAmt = Math.min(dest.length, mReadBuffer.length);
191 | numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
192 | timeoutMillis);
193 | if (numBytesRead < 0) {
194 | // This sucks: we get -1 on timeout, not 0 as preferred.
195 | // We *should* use UsbRequest, except it has a bug/api oversight
196 | // where there is no way to determine the number of bytes read
197 | // in response :\ -- http://b.android.com/28023
198 | if (timeoutMillis == Integer.MAX_VALUE) {
199 | // Hack: Special case "~infinite timeout" as an error.
200 | return -1;
201 | }
202 | return 0;
203 | }
204 | System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
205 | }
206 | return numBytesRead;
207 | }
208 |
209 | @Override
210 | public int write(byte[] src, int timeoutMillis) throws IOException {
211 | // TODO(mikey): Nearly identical to FtdiSerial write. Refactor.
212 | int offset = 0;
213 |
214 | while (offset < src.length) {
215 | final int writeLength;
216 | final int amtWritten;
217 |
218 | synchronized (mWriteBufferLock) {
219 | final byte[] writeBuffer;
220 |
221 | writeLength = Math.min(src.length - offset, mWriteBuffer.length);
222 | if (offset == 0) {
223 | writeBuffer = src;
224 | } else {
225 | // bulkTransfer does not support offsets, make a copy.
226 | System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
227 | writeBuffer = mWriteBuffer;
228 | }
229 |
230 | amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
231 | timeoutMillis);
232 | }
233 | if (amtWritten <= 0) {
234 | throw new IOException("Error writing " + writeLength
235 | + " bytes at offset " + offset + " length=" + src.length);
236 | }
237 |
238 | Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
239 | offset += amtWritten;
240 | }
241 | return offset;
242 | }
243 |
244 | @Override
245 | public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
246 | byte stopBitsByte;
247 | switch (stopBits) {
248 | case STOPBITS_1: stopBitsByte = 0; break;
249 | case STOPBITS_1_5: stopBitsByte = 1; break;
250 | case STOPBITS_2: stopBitsByte = 2; break;
251 | default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
252 | }
253 |
254 | byte parityBitesByte;
255 | switch (parity) {
256 | case PARITY_NONE: parityBitesByte = 0; break;
257 | case PARITY_ODD: parityBitesByte = 1; break;
258 | case PARITY_EVEN: parityBitesByte = 2; break;
259 | case PARITY_MARK: parityBitesByte = 3; break;
260 | case PARITY_SPACE: parityBitesByte = 4; break;
261 | default: throw new IllegalArgumentException("Bad value for parity: " + parity);
262 | }
263 |
264 | byte[] msg = {
265 | (byte) ( baudRate & 0xff),
266 | (byte) ((baudRate >> 8 ) & 0xff),
267 | (byte) ((baudRate >> 16) & 0xff),
268 | (byte) ((baudRate >> 24) & 0xff),
269 | stopBitsByte,
270 | parityBitesByte,
271 | (byte) dataBits};
272 | sendAcmControlMessage(SET_LINE_CODING, 0, msg);
273 | }
274 |
275 | @Override
276 | public boolean getCD() throws IOException {
277 | return false; // TODO
278 | }
279 |
280 | @Override
281 | public boolean getCTS() throws IOException {
282 | return false; // TODO
283 | }
284 |
285 | @Override
286 | public boolean getDSR() throws IOException {
287 | return false; // TODO
288 | }
289 |
290 | @Override
291 | public boolean getDTR() throws IOException {
292 | return mDtr;
293 | }
294 |
295 | @Override
296 | public void setDTR(boolean value) throws IOException {
297 | mDtr = value;
298 | setDtrRts();
299 | }
300 |
301 | @Override
302 | public boolean getRI() throws IOException {
303 | return false; // TODO
304 | }
305 |
306 | @Override
307 | public boolean getRTS() throws IOException {
308 | return mRts;
309 | }
310 |
311 | @Override
312 | public void setRTS(boolean value) throws IOException {
313 | mRts = value;
314 | setDtrRts();
315 | }
316 |
317 | private void setDtrRts() {
318 | int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
319 | sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
320 | }
321 |
322 | }
323 |
324 | public static Map getSupportedDevices() {
325 | final Map supportedDevices = new LinkedHashMap();
326 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO),
327 | new int[] {
328 | UsbId.ARDUINO_UNO,
329 | UsbId.ARDUINO_UNO_R3,
330 | UsbId.ARDUINO_MEGA_2560,
331 | UsbId.ARDUINO_MEGA_2560_R3,
332 | UsbId.ARDUINO_SERIAL_ADAPTER,
333 | UsbId.ARDUINO_SERIAL_ADAPTER_R3,
334 | UsbId.ARDUINO_MEGA_ADK,
335 | UsbId.ARDUINO_MEGA_ADK_R3,
336 | UsbId.ARDUINO_LEONARDO,
337 | });
338 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH),
339 | new int[] {
340 | UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL,
341 | });
342 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ATMEL),
343 | new int[] {
344 | UsbId.ATMEL_LUFA_CDC_DEMO_APP,
345 | });
346 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_LEAFLABS),
347 | new int[] {
348 | UsbId.LEAFLABS_MAPLE,
349 | });
350 | return supportedDevices;
351 | }
352 |
353 | }
354 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/CommonUsbSerialPort.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbDevice;
25 | import android.hardware.usb.UsbDeviceConnection;
26 |
27 | import java.io.IOException;
28 |
29 | /**
30 | * A base class shared by several driver implementations.
31 | *
32 | * @author mike wakerly (opensource@hoho.com)
33 | */
34 | public abstract class CommonUsbSerialPort implements UsbSerialPort {
35 |
36 | public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
37 | public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024;
38 |
39 | protected final UsbDevice mDevice;
40 | protected final int mPortNumber;
41 |
42 | // non-null when open()
43 | protected UsbDeviceConnection mConnection = null;
44 |
45 | protected final Object mReadBufferLock = new Object();
46 | protected final Object mWriteBufferLock = new Object();
47 |
48 | /** Internal read buffer. Guarded by {@link #mReadBufferLock}. */
49 | protected byte[] mReadBuffer;
50 |
51 | /** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */
52 | protected byte[] mWriteBuffer;
53 |
54 | public CommonUsbSerialPort(UsbDevice device, int portNumber) {
55 | mDevice = device;
56 | mPortNumber = portNumber;
57 |
58 | mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE];
59 | mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return String.format("<%s device_name=%s device_id=%s port_number=%s>",
65 | getClass().getSimpleName(), mDevice.getDeviceName(),
66 | mDevice.getDeviceId(), mPortNumber);
67 | }
68 |
69 | /**
70 | * Returns the currently-bound USB device.
71 | *
72 | * @return the device
73 | */
74 | public final UsbDevice getDevice() {
75 | return mDevice;
76 | }
77 |
78 | @Override
79 | public int getPortNumber() {
80 | return mPortNumber;
81 | }
82 |
83 | /**
84 | * Returns the device serial number
85 | * @return serial number
86 | */
87 | @Override
88 | public String getSerial() {
89 | return mConnection.getSerial();
90 | }
91 |
92 | /**
93 | * Sets the size of the internal buffer used to exchange data with the USB
94 | * stack for read operations. Most users should not need to change this.
95 | *
96 | * @param bufferSize the size in bytes
97 | */
98 | public final void setReadBufferSize(int bufferSize) {
99 | synchronized (mReadBufferLock) {
100 | if (bufferSize == mReadBuffer.length) {
101 | return;
102 | }
103 | mReadBuffer = new byte[bufferSize];
104 | }
105 | }
106 |
107 | /**
108 | * Sets the size of the internal buffer used to exchange data with the USB
109 | * stack for write operations. Most users should not need to change this.
110 | *
111 | * @param bufferSize the size in bytes
112 | */
113 | public final void setWriteBufferSize(int bufferSize) {
114 | synchronized (mWriteBufferLock) {
115 | if (bufferSize == mWriteBuffer.length) {
116 | return;
117 | }
118 | mWriteBuffer = new byte[bufferSize];
119 | }
120 | }
121 |
122 | @Override
123 | public abstract void open(UsbDeviceConnection connection) throws IOException;
124 |
125 | @Override
126 | public abstract void close() throws IOException;
127 |
128 | @Override
129 | public abstract int read(final byte[] dest, final int timeoutMillis) throws IOException;
130 |
131 | @Override
132 | public abstract int write(final byte[] src, final int timeoutMillis) throws IOException;
133 |
134 | @Override
135 | public abstract void setParameters(
136 | int baudRate, int dataBits, int stopBits, int parity) throws IOException;
137 |
138 | @Override
139 | public abstract boolean getCD() throws IOException;
140 |
141 | @Override
142 | public abstract boolean getCTS() throws IOException;
143 |
144 | @Override
145 | public abstract boolean getDSR() throws IOException;
146 |
147 | @Override
148 | public abstract boolean getDTR() throws IOException;
149 |
150 | @Override
151 | public abstract void setDTR(boolean value) throws IOException;
152 |
153 | @Override
154 | public abstract boolean getRI() throws IOException;
155 |
156 | @Override
157 | public abstract boolean getRTS() throws IOException;
158 |
159 | @Override
160 | public abstract void setRTS(boolean value) throws IOException;
161 |
162 | @Override
163 | public boolean purgeHwBuffers(boolean flushReadBuffers, boolean flushWriteBuffers) throws IOException {
164 | return !flushReadBuffers && !flushWriteBuffers;
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/Cp21xxSerialDriver.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbConstants;
25 | import android.hardware.usb.UsbDevice;
26 | import android.hardware.usb.UsbDeviceConnection;
27 | import android.hardware.usb.UsbEndpoint;
28 | import android.hardware.usb.UsbInterface;
29 | import android.util.Log;
30 |
31 | import java.io.IOException;
32 | import java.util.Collections;
33 | import java.util.LinkedHashMap;
34 | import java.util.List;
35 | import java.util.Map;
36 |
37 | public class Cp21xxSerialDriver implements UsbSerialDriver {
38 |
39 | private static final String TAG = Cp21xxSerialDriver.class.getSimpleName();
40 |
41 | private final UsbDevice mDevice;
42 | private final UsbSerialPort mPort;
43 |
44 | public Cp21xxSerialDriver(UsbDevice device) {
45 | mDevice = device;
46 | mPort = new Cp21xxSerialPort(mDevice, 0);
47 | }
48 |
49 | @Override
50 | public UsbDevice getDevice() {
51 | return mDevice;
52 | }
53 |
54 | @Override
55 | public List getPorts() {
56 | return Collections.singletonList(mPort);
57 | }
58 |
59 | public class Cp21xxSerialPort extends CommonUsbSerialPort {
60 |
61 | private static final int DEFAULT_BAUD_RATE = 9600;
62 |
63 | private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
64 |
65 | /*
66 | * Configuration Request Types
67 | */
68 | private static final int REQTYPE_HOST_TO_DEVICE = 0x41;
69 |
70 | /*
71 | * Configuration Request Codes
72 | */
73 | private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
74 | private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
75 | private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
76 | private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
77 | private static final int SILABSER_SET_BAUDRATE = 0x1E;
78 | private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12;
79 |
80 | private static final int FLUSH_READ_CODE = 0x0a;
81 | private static final int FLUSH_WRITE_CODE = 0x05;
82 |
83 | /*
84 | * SILABSER_IFC_ENABLE_REQUEST_CODE
85 | */
86 | private static final int UART_ENABLE = 0x0001;
87 | private static final int UART_DISABLE = 0x0000;
88 |
89 | /*
90 | * SILABSER_SET_BAUDDIV_REQUEST_CODE
91 | */
92 | private static final int BAUD_RATE_GEN_FREQ = 0x384000;
93 |
94 | /*
95 | * SILABSER_SET_MHS_REQUEST_CODE
96 | */
97 | private static final int MCR_DTR = 0x0001;
98 | private static final int MCR_RTS = 0x0002;
99 | private static final int MCR_ALL = 0x0003;
100 |
101 | private static final int CONTROL_WRITE_DTR = 0x0100;
102 | private static final int CONTROL_WRITE_RTS = 0x0200;
103 |
104 | private UsbEndpoint mReadEndpoint;
105 | private UsbEndpoint mWriteEndpoint;
106 |
107 | public Cp21xxSerialPort(UsbDevice device, int portNumber) {
108 | super(device, portNumber);
109 | }
110 |
111 | @Override
112 | public UsbSerialDriver getDriver() {
113 | return Cp21xxSerialDriver.this;
114 | }
115 |
116 | private int setConfigSingle(int request, int value) {
117 | return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
118 | 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
119 | }
120 |
121 | @Override
122 | public void open(UsbDeviceConnection connection) throws IOException {
123 | if (mConnection != null) {
124 | throw new IOException("Already opened.");
125 | }
126 |
127 | mConnection = connection;
128 | boolean opened = false;
129 | try {
130 | for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
131 | UsbInterface usbIface = mDevice.getInterface(i);
132 | if (mConnection.claimInterface(usbIface, true)) {
133 | Log.d(TAG, "claimInterface " + i + " SUCCESS");
134 | } else {
135 | Log.d(TAG, "claimInterface " + i + " FAIL");
136 | }
137 | }
138 |
139 | UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
140 | for (int i = 0; i < dataIface.getEndpointCount(); i++) {
141 | UsbEndpoint ep = dataIface.getEndpoint(i);
142 | if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
143 | if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
144 | mReadEndpoint = ep;
145 | } else {
146 | mWriteEndpoint = ep;
147 | }
148 | }
149 | }
150 |
151 | setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE);
152 | setConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS);
153 | setConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);
154 | // setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY);
155 | opened = true;
156 | } finally {
157 | if (!opened) {
158 | try {
159 | close();
160 | } catch (IOException e) {
161 | // Ignore IOExceptions during close()
162 | }
163 | }
164 | }
165 | }
166 |
167 | @Override
168 | public void close() throws IOException {
169 | if (mConnection == null) {
170 | throw new IOException("Already closed");
171 | }
172 | try {
173 | setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
174 | mConnection.close();
175 | } finally {
176 | mConnection = null;
177 | }
178 | }
179 |
180 | @Override
181 | public int read(byte[] dest, int timeoutMillis) throws IOException {
182 | final int numBytesRead;
183 | synchronized (mReadBufferLock) {
184 | int readAmt = Math.min(dest.length, mReadBuffer.length);
185 | numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
186 | timeoutMillis);
187 | if (numBytesRead < 0) {
188 | // This sucks: we get -1 on timeout, not 0 as preferred.
189 | // We *should* use UsbRequest, except it has a bug/api oversight
190 | // where there is no way to determine the number of bytes read
191 | // in response :\ -- http://b.android.com/28023
192 | return 0;
193 | }
194 | System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
195 | }
196 | return numBytesRead;
197 | }
198 |
199 | @Override
200 | public int write(byte[] src, int timeoutMillis) throws IOException {
201 | int offset = 0;
202 |
203 | while (offset < src.length) {
204 | final int writeLength;
205 | final int amtWritten;
206 |
207 | synchronized (mWriteBufferLock) {
208 | final byte[] writeBuffer;
209 |
210 | writeLength = Math.min(src.length - offset, mWriteBuffer.length);
211 | if (offset == 0) {
212 | writeBuffer = src;
213 | } else {
214 | // bulkTransfer does not support offsets, make a copy.
215 | System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
216 | writeBuffer = mWriteBuffer;
217 | }
218 |
219 | amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
220 | timeoutMillis);
221 | }
222 | if (amtWritten <= 0) {
223 | throw new IOException("Error writing " + writeLength
224 | + " bytes at offset " + offset + " length=" + src.length);
225 | }
226 |
227 | Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
228 | offset += amtWritten;
229 | }
230 | return offset;
231 | }
232 |
233 | private void setBaudRate(int baudRate) throws IOException {
234 | byte[] data = new byte[] {
235 | (byte) ( baudRate & 0xff),
236 | (byte) ((baudRate >> 8 ) & 0xff),
237 | (byte) ((baudRate >> 16) & 0xff),
238 | (byte) ((baudRate >> 24) & 0xff)
239 | };
240 | int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
241 | 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
242 | if (ret < 0) {
243 | throw new IOException("Error setting baud rate.");
244 | }
245 | }
246 |
247 | @Override
248 | public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
249 | throws IOException {
250 | setBaudRate(baudRate);
251 |
252 | int configDataBits = 0;
253 | switch (dataBits) {
254 | case DATABITS_5:
255 | configDataBits |= 0x0500;
256 | break;
257 | case DATABITS_6:
258 | configDataBits |= 0x0600;
259 | break;
260 | case DATABITS_7:
261 | configDataBits |= 0x0700;
262 | break;
263 | case DATABITS_8:
264 | configDataBits |= 0x0800;
265 | break;
266 | default:
267 | configDataBits |= 0x0800;
268 | break;
269 | }
270 |
271 | switch (parity) {
272 | case PARITY_ODD:
273 | configDataBits |= 0x0010;
274 | break;
275 | case PARITY_EVEN:
276 | configDataBits |= 0x0020;
277 | break;
278 | }
279 |
280 | switch (stopBits) {
281 | case STOPBITS_1:
282 | configDataBits |= 0;
283 | break;
284 | case STOPBITS_2:
285 | configDataBits |= 2;
286 | break;
287 | }
288 | setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
289 | }
290 |
291 | @Override
292 | public boolean getCD() throws IOException {
293 | return false;
294 | }
295 |
296 | @Override
297 | public boolean getCTS() throws IOException {
298 | return false;
299 | }
300 |
301 | @Override
302 | public boolean getDSR() throws IOException {
303 | return false;
304 | }
305 |
306 | @Override
307 | public boolean getDTR() throws IOException {
308 | return true;
309 | }
310 |
311 | @Override
312 | public void setDTR(boolean value) throws IOException {
313 | }
314 |
315 | @Override
316 | public boolean getRI() throws IOException {
317 | return false;
318 | }
319 |
320 | @Override
321 | public boolean getRTS() throws IOException {
322 | return true;
323 | }
324 |
325 | @Override
326 | public void setRTS(boolean value) throws IOException {
327 | }
328 |
329 | @Override
330 | public boolean purgeHwBuffers(boolean purgeReadBuffers,
331 | boolean purgeWriteBuffers) throws IOException {
332 | int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
333 | | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
334 |
335 | if (value != 0) {
336 | setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value);
337 | }
338 |
339 | return true;
340 | }
341 |
342 | }
343 |
344 | public static Map getSupportedDevices() {
345 | final Map supportedDevices = new LinkedHashMap();
346 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILABS),
347 | new int[] {
348 | UsbId.SILABS_CP2102,
349 | UsbId.SILABS_CP2105,
350 | UsbId.SILABS_CP2108,
351 | UsbId.SILABS_CP2110
352 | });
353 | return supportedDevices;
354 | }
355 |
356 | }
357 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbConstants;
25 | import android.hardware.usb.UsbDevice;
26 | import android.hardware.usb.UsbDeviceConnection;
27 | import android.hardware.usb.UsbEndpoint;
28 | import android.hardware.usb.UsbRequest;
29 | import android.util.Log;
30 |
31 | import com.hoho.android.usbserial.util.HexDump;
32 |
33 | import java.io.IOException;
34 | import java.nio.ByteBuffer;
35 | import java.util.Collections;
36 | import java.util.LinkedHashMap;
37 | import java.util.List;
38 | import java.util.Map;
39 |
40 | /**
41 | * A {@link CommonUsbSerialPort} implementation for a variety of FTDI devices
42 | *
43 | * This driver is based on libftdi, and is
45 | * copyright and subject to the following terms:
46 | *
47 | *
48 | * Copyright (C) 2003 by Intra2net AG
49 | *
50 | * This program is free software; you can redistribute it and/or modify
51 | * it under the terms of the GNU Lesser General Public License
52 | * version 2.1 as published by the Free Software Foundation;
53 | *
54 | * opensource@intra2net.com
55 | * http://www.intra2net.com/en/developer/libftdi
56 | *
57 | *
58 | *
59 | *
60 | * Some FTDI devices have not been tested; see later listing of supported and
61 | * unsupported devices. Devices listed as "supported" support the following
62 | * features:
63 | *
64 | * - Read and write of serial data (see
65 | * {@link CommonUsbSerialPort#read(byte[], int)} and
66 | * {@link CommonUsbSerialPort#write(byte[], int)}.
67 | * - Setting serial line parameters (see
68 | * {@link CommonUsbSerialPort#setParameters(int, int, int, int)}.
69 | *
70 | *
71 | *
72 | * Supported and tested devices:
73 | *
74 | * - {@value DeviceType#TYPE_R}
75 | *
76 | *
77 | *
78 | * Unsupported but possibly working devices (please contact the author with
79 | * feedback or patches):
80 | *
81 | * - {@value DeviceType#TYPE_2232C}
82 | * - {@value DeviceType#TYPE_2232H}
83 | * - {@value DeviceType#TYPE_4232H}
84 | * - {@value DeviceType#TYPE_AM}
85 | * - {@value DeviceType#TYPE_BM}
86 | *
87 | *
88 | *
89 | * @author mike wakerly (opensource@hoho.com)
90 | * @see USB Serial
91 | * for Android project page
92 | * @see FTDI Homepage
93 | * @see libftdi
94 | */
95 | public class FtdiSerialDriver implements UsbSerialDriver {
96 |
97 | private final UsbDevice mDevice;
98 | private final UsbSerialPort mPort;
99 |
100 | /**
101 | * FTDI chip types.
102 | */
103 | private static enum DeviceType {
104 | TYPE_BM, TYPE_AM, TYPE_2232C, TYPE_R, TYPE_2232H, TYPE_4232H;
105 | }
106 |
107 | public FtdiSerialDriver(UsbDevice device) {
108 | mDevice = device;
109 | mPort = new FtdiSerialPort(mDevice, 0);
110 | }
111 | @Override
112 | public UsbDevice getDevice() {
113 | return mDevice;
114 | }
115 |
116 | @Override
117 | public List getPorts() {
118 | return Collections.singletonList(mPort);
119 | }
120 |
121 | private class FtdiSerialPort extends CommonUsbSerialPort {
122 |
123 | public static final int USB_TYPE_STANDARD = 0x00 << 5;
124 | public static final int USB_TYPE_CLASS = 0x00 << 5;
125 | public static final int USB_TYPE_VENDOR = 0x00 << 5;
126 | public static final int USB_TYPE_RESERVED = 0x00 << 5;
127 |
128 | public static final int USB_RECIP_DEVICE = 0x00;
129 | public static final int USB_RECIP_INTERFACE = 0x01;
130 | public static final int USB_RECIP_ENDPOINT = 0x02;
131 | public static final int USB_RECIP_OTHER = 0x03;
132 |
133 | public static final int USB_ENDPOINT_IN = 0x80;
134 | public static final int USB_ENDPOINT_OUT = 0x00;
135 |
136 | public static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
137 | public static final int USB_READ_TIMEOUT_MILLIS = 5000;
138 |
139 | // From ftdi.h
140 | /**
141 | * Reset the port.
142 | */
143 | private static final int SIO_RESET_REQUEST = 0;
144 |
145 | /**
146 | * Set the modem control register.
147 | */
148 | private static final int SIO_MODEM_CTRL_REQUEST = 1;
149 |
150 | /**
151 | * Set flow control register.
152 | */
153 | private static final int SIO_SET_FLOW_CTRL_REQUEST = 2;
154 |
155 | /**
156 | * Set baud rate.
157 | */
158 | private static final int SIO_SET_BAUD_RATE_REQUEST = 3;
159 |
160 | /**
161 | * Set the data characteristics of the port.
162 | */
163 | private static final int SIO_SET_DATA_REQUEST = 4;
164 |
165 | private static final int SIO_RESET_SIO = 0;
166 | private static final int SIO_RESET_PURGE_RX = 1;
167 | private static final int SIO_RESET_PURGE_TX = 2;
168 |
169 | public static final int FTDI_DEVICE_OUT_REQTYPE =
170 | UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT;
171 |
172 | public static final int FTDI_DEVICE_IN_REQTYPE =
173 | UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN;
174 |
175 | /**
176 | * Length of the modem status header, transmitted with every read.
177 | */
178 | private static final int MODEM_STATUS_HEADER_LENGTH = 2;
179 |
180 | private final String TAG = FtdiSerialDriver.class.getSimpleName();
181 |
182 | private DeviceType mType;
183 |
184 | private int mInterface = 0; /* INTERFACE_ANY */
185 |
186 | private int mMaxPacketSize = 64; // TODO(mikey): detect
187 |
188 | /**
189 | * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads
190 | * since it gives no indication of number of bytes read. Set this to
191 | * {@code true} on platforms where it is fixed.
192 | */
193 | private static final boolean ENABLE_ASYNC_READS = false;
194 |
195 | public FtdiSerialPort(UsbDevice device, int portNumber) {
196 | super(device, portNumber);
197 | }
198 |
199 | @Override
200 | public UsbSerialDriver getDriver() {
201 | return FtdiSerialDriver.this;
202 | }
203 |
204 | /**
205 | * Filter FTDI status bytes from buffer
206 | * @param src The source buffer (which contains status bytes)
207 | * @param dest The destination buffer to write the status bytes into (can be src)
208 | * @param totalBytesRead Number of bytes read to src
209 | * @param maxPacketSize The USB endpoint max packet size
210 | * @return The number of payload bytes
211 | */
212 | private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) {
213 | final int packetsCount = totalBytesRead / maxPacketSize + (totalBytesRead % maxPacketSize == 0 ? 0 : 1);
214 | for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) {
215 | final int count = (packetIdx == (packetsCount - 1))
216 | ? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH
217 | : maxPacketSize - MODEM_STATUS_HEADER_LENGTH;
218 | if (count > 0) {
219 | System.arraycopy(src,
220 | packetIdx * maxPacketSize + MODEM_STATUS_HEADER_LENGTH,
221 | dest,
222 | packetIdx * (maxPacketSize - MODEM_STATUS_HEADER_LENGTH),
223 | count);
224 | }
225 | }
226 |
227 | return totalBytesRead - (packetsCount * 2);
228 | }
229 |
230 | public void reset() throws IOException {
231 | int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
232 | SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
233 | if (result != 0) {
234 | throw new IOException("Reset failed: result=" + result);
235 | }
236 |
237 | // TODO(mikey): autodetect.
238 | mType = DeviceType.TYPE_R;
239 | }
240 |
241 | @Override
242 | public void open(UsbDeviceConnection connection) throws IOException {
243 | if (mConnection != null) {
244 | throw new IOException("Already open");
245 | }
246 | mConnection = connection;
247 |
248 | boolean opened = false;
249 | try {
250 | for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
251 | if (connection.claimInterface(mDevice.getInterface(i), true)) {
252 | Log.d(TAG, "claimInterface " + i + " SUCCESS");
253 | } else {
254 | throw new IOException("Error claiming interface " + i);
255 | }
256 | }
257 | reset();
258 | opened = true;
259 | } finally {
260 | if (!opened) {
261 | close();
262 | mConnection = null;
263 | }
264 | }
265 | }
266 |
267 | @Override
268 | public void close() throws IOException {
269 | if (mConnection == null) {
270 | throw new IOException("Already closed");
271 | }
272 | try {
273 | mConnection.close();
274 | } finally {
275 | mConnection = null;
276 | }
277 | }
278 |
279 | @Override
280 | public int read(byte[] dest, int timeoutMillis) throws IOException {
281 | final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0);
282 |
283 | if (ENABLE_ASYNC_READS) {
284 | final int readAmt;
285 | synchronized (mReadBufferLock) {
286 | // mReadBuffer is only used for maximum read size.
287 | readAmt = Math.min(dest.length, mReadBuffer.length);
288 | }
289 |
290 | final UsbRequest request = new UsbRequest();
291 | request.initialize(mConnection, endpoint);
292 |
293 | final ByteBuffer buf = ByteBuffer.wrap(dest);
294 | if (!request.queue(buf, readAmt)) {
295 | throw new IOException("Error queueing request.");
296 | }
297 |
298 | final UsbRequest response = mConnection.requestWait();
299 | if (response == null) {
300 | throw new IOException("Null response");
301 | }
302 |
303 | final int payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH;
304 | if (payloadBytesRead > 0) {
305 | Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
306 | return payloadBytesRead;
307 | } else {
308 | return 0;
309 | }
310 | } else {
311 | final int totalBytesRead;
312 |
313 | synchronized (mReadBufferLock) {
314 | final int readAmt = Math.min(dest.length, mReadBuffer.length);
315 | totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer,
316 | readAmt, timeoutMillis);
317 |
318 | if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
319 | throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
320 | }
321 |
322 | return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize());
323 | }
324 | }
325 | }
326 |
327 | @Override
328 | public int write(byte[] src, int timeoutMillis) throws IOException {
329 | final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1);
330 | int offset = 0;
331 |
332 | while (offset < src.length) {
333 | final int writeLength;
334 | final int amtWritten;
335 |
336 | synchronized (mWriteBufferLock) {
337 | final byte[] writeBuffer;
338 |
339 | writeLength = Math.min(src.length - offset, mWriteBuffer.length);
340 | if (offset == 0) {
341 | writeBuffer = src;
342 | } else {
343 | // bulkTransfer does not support offsets, make a copy.
344 | System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
345 | writeBuffer = mWriteBuffer;
346 | }
347 |
348 | amtWritten = mConnection.bulkTransfer(endpoint, writeBuffer, writeLength,
349 | timeoutMillis);
350 | }
351 |
352 | if (amtWritten <= 0) {
353 | throw new IOException("Error writing " + writeLength
354 | + " bytes at offset " + offset + " length=" + src.length);
355 | }
356 |
357 | Log.d(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength);
358 | offset += amtWritten;
359 | }
360 | return offset;
361 | }
362 |
363 | private int setBaudRate(int baudRate) throws IOException {
364 | long[] vals = convertBaudrate(baudRate);
365 | long actualBaudrate = vals[0];
366 | long index = vals[1];
367 | long value = vals[2];
368 | int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
369 | SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index,
370 | null, 0, USB_WRITE_TIMEOUT_MILLIS);
371 | if (result != 0) {
372 | throw new IOException("Setting baudrate failed: result=" + result);
373 | }
374 | return (int) actualBaudrate;
375 | }
376 |
377 | @Override
378 | public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
379 | throws IOException {
380 | setBaudRate(baudRate);
381 |
382 | int config = dataBits;
383 |
384 | switch (parity) {
385 | case PARITY_NONE:
386 | config |= (0x00 << 8);
387 | break;
388 | case PARITY_ODD:
389 | config |= (0x01 << 8);
390 | break;
391 | case PARITY_EVEN:
392 | config |= (0x02 << 8);
393 | break;
394 | case PARITY_MARK:
395 | config |= (0x03 << 8);
396 | break;
397 | case PARITY_SPACE:
398 | config |= (0x04 << 8);
399 | break;
400 | default:
401 | throw new IllegalArgumentException("Unknown parity value: " + parity);
402 | }
403 |
404 | switch (stopBits) {
405 | case STOPBITS_1:
406 | config |= (0x00 << 11);
407 | break;
408 | case STOPBITS_1_5:
409 | config |= (0x01 << 11);
410 | break;
411 | case STOPBITS_2:
412 | config |= (0x02 << 11);
413 | break;
414 | default:
415 | throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
416 | }
417 |
418 | int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
419 | SIO_SET_DATA_REQUEST, config, 0 /* index */,
420 | null, 0, USB_WRITE_TIMEOUT_MILLIS);
421 | if (result != 0) {
422 | throw new IOException("Setting parameters failed: result=" + result);
423 | }
424 | }
425 |
426 | private long[] convertBaudrate(int baudrate) {
427 | // TODO(mikey): Braindead transcription of libfti method. Clean up,
428 | // using more idiomatic Java where possible.
429 | int divisor = 24000000 / baudrate;
430 | int bestDivisor = 0;
431 | int bestBaud = 0;
432 | int bestBaudDiff = 0;
433 | int fracCode[] = {
434 | 0, 3, 2, 4, 1, 5, 6, 7
435 | };
436 |
437 | for (int i = 0; i < 2; i++) {
438 | int tryDivisor = divisor + i;
439 | int baudEstimate;
440 | int baudDiff;
441 |
442 | if (tryDivisor <= 8) {
443 | // Round up to minimum supported divisor
444 | tryDivisor = 8;
445 | } else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) {
446 | // BM doesn't support divisors 9 through 11 inclusive
447 | tryDivisor = 12;
448 | } else if (divisor < 16) {
449 | // AM doesn't support divisors 9 through 15 inclusive
450 | tryDivisor = 16;
451 | } else {
452 | if (mType == DeviceType.TYPE_AM) {
453 | // TODO
454 | } else {
455 | if (tryDivisor > 0x1FFFF) {
456 | // Round down to maximum supported divisor value (for
457 | // BM)
458 | tryDivisor = 0x1FFFF;
459 | }
460 | }
461 | }
462 |
463 | // Get estimated baud rate (to nearest integer)
464 | baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor;
465 |
466 | // Get absolute difference from requested baud rate
467 | if (baudEstimate < baudrate) {
468 | baudDiff = baudrate - baudEstimate;
469 | } else {
470 | baudDiff = baudEstimate - baudrate;
471 | }
472 |
473 | if (i == 0 || baudDiff < bestBaudDiff) {
474 | // Closest to requested baud rate so far
475 | bestDivisor = tryDivisor;
476 | bestBaud = baudEstimate;
477 | bestBaudDiff = baudDiff;
478 | if (baudDiff == 0) {
479 | // Spot on! No point trying
480 | break;
481 | }
482 | }
483 | }
484 |
485 | // Encode the best divisor value
486 | long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14);
487 | // Deal with special cases for encoded value
488 | if (encodedDivisor == 1) {
489 | encodedDivisor = 0; // 3000000 baud
490 | } else if (encodedDivisor == 0x4001) {
491 | encodedDivisor = 1; // 2000000 baud (BM only)
492 | }
493 |
494 | // Split into "value" and "index" values
495 | long value = encodedDivisor & 0xFFFF;
496 | long index;
497 | if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H
498 | || mType == DeviceType.TYPE_4232H) {
499 | index = (encodedDivisor >> 8) & 0xffff;
500 | index &= 0xFF00;
501 | index |= 0 /* TODO mIndex */;
502 | } else {
503 | index = (encodedDivisor >> 16) & 0xffff;
504 | }
505 |
506 | // Return the nearest baud rate
507 | return new long[] {
508 | bestBaud, index, value
509 | };
510 | }
511 |
512 | @Override
513 | public boolean getCD() throws IOException {
514 | return false;
515 | }
516 |
517 | @Override
518 | public boolean getCTS() throws IOException {
519 | return false;
520 | }
521 |
522 | @Override
523 | public boolean getDSR() throws IOException {
524 | return false;
525 | }
526 |
527 | @Override
528 | public boolean getDTR() throws IOException {
529 | return false;
530 | }
531 |
532 | @Override
533 | public void setDTR(boolean value) throws IOException {
534 | }
535 |
536 | @Override
537 | public boolean getRI() throws IOException {
538 | return false;
539 | }
540 |
541 | @Override
542 | public boolean getRTS() throws IOException {
543 | return false;
544 | }
545 |
546 | @Override
547 | public void setRTS(boolean value) throws IOException {
548 | }
549 |
550 | @Override
551 | public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
552 | if (purgeReadBuffers) {
553 | int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
554 | SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
555 | if (result != 0) {
556 | throw new IOException("Flushing RX failed: result=" + result);
557 | }
558 | }
559 |
560 | if (purgeWriteBuffers) {
561 | int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
562 | SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
563 | if (result != 0) {
564 | throw new IOException("Flushing RX failed: result=" + result);
565 | }
566 | }
567 | return true;
568 | }
569 | }
570 |
571 | public static Map getSupportedDevices() {
572 | final Map supportedDevices = new LinkedHashMap();
573 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI),
574 | new int[] {
575 | UsbId.FTDI_FT232R,
576 | UsbId.FTDI_FT231X,
577 | });
578 | return supportedDevices;
579 | }
580 |
581 | }
582 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/ProbeTable.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.util.Pair;
25 |
26 | import java.lang.reflect.InvocationTargetException;
27 | import java.lang.reflect.Method;
28 | import java.util.LinkedHashMap;
29 | import java.util.Map;
30 |
31 | /**
32 | * Maps (vendor id, product id) pairs to the corresponding serial driver.
33 | *
34 | * @author mike wakerly (opensource@hoho.com)
35 | */
36 | public class ProbeTable {
37 |
38 | private final Map, Class extends UsbSerialDriver>> mProbeTable =
39 | new LinkedHashMap, Class extends UsbSerialDriver>>();
40 |
41 | /**
42 | * Adds or updates a (vendor, product) pair in the table.
43 | *
44 | * @param vendorId the USB vendor id
45 | * @param productId the USB product id
46 | * @param driverClass the driver class responsible for this pair
47 | * @return {@code this}, for chaining
48 | */
49 | public ProbeTable addProduct(int vendorId, int productId,
50 | Class extends UsbSerialDriver> driverClass) {
51 | mProbeTable.put(Pair.create(vendorId, productId), driverClass);
52 | return this;
53 | }
54 |
55 | /**
56 | * Internal method to add all supported products from
57 | * {@code getSupportedProducts} static method.
58 | *
59 | * @param driverClass
60 | * @return
61 | */
62 | @SuppressWarnings("unchecked")
63 | public ProbeTable addDriver(Class extends UsbSerialDriver> driverClass) {
64 | final Method method;
65 |
66 | try {
67 | method = driverClass.getMethod("getSupportedDevices");
68 | } catch (SecurityException e) {
69 | throw new RuntimeException(e);
70 | } catch (NoSuchMethodException e) {
71 | throw new RuntimeException(e);
72 | }
73 |
74 | final Map devices;
75 | try {
76 | devices = (Map) method.invoke(null);
77 | } catch (IllegalArgumentException e) {
78 | throw new RuntimeException(e);
79 | } catch (IllegalAccessException e) {
80 | throw new RuntimeException(e);
81 | } catch (InvocationTargetException e) {
82 | throw new RuntimeException(e);
83 | }
84 |
85 | for (Map.Entry entry : devices.entrySet()) {
86 | final int vendorId = entry.getKey().intValue();
87 | for (int productId : entry.getValue()) {
88 | addProduct(vendorId, productId, driverClass);
89 | }
90 | }
91 |
92 | return this;
93 | }
94 |
95 | /**
96 | * Returns the driver for the given (vendor, product) pair, or {@code null}
97 | * if no match.
98 | *
99 | * @param vendorId the USB vendor id
100 | * @param productId the USB product id
101 | * @return the driver class matching this pair, or {@code null}
102 | */
103 | public Class extends UsbSerialDriver> findDriver(int vendorId, int productId) {
104 | final Pair pair = Pair.create(vendorId, productId);
105 | return mProbeTable.get(pair);
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java:
--------------------------------------------------------------------------------
1 | /* This library is free software; you can redistribute it and/or
2 | * modify it under the terms of the GNU Lesser General Public
3 | * License as published by the Free Software Foundation; either
4 | * version 2.1 of the License, or (at your option) any later version.
5 | *
6 | * This library is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 | * Lesser General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU Lesser General Public
12 | * License along with this library; if not, write to the Free Software
13 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
14 | * USA.
15 | *
16 | * Project home page: https://github.com/mik3y/usb-serial-for-android
17 | */
18 |
19 | /*
20 | * Ported to usb-serial-for-android
21 | * by Felix Hädicke
22 | *
23 | * Based on the pyprolific driver written
24 | * by Emmanuel Blot
25 | * See https://github.com/eblot/pyftdi
26 | */
27 |
28 | package com.hoho.android.usbserial.driver;
29 |
30 | import android.hardware.usb.UsbConstants;
31 | import android.hardware.usb.UsbDevice;
32 | import android.hardware.usb.UsbDeviceConnection;
33 | import android.hardware.usb.UsbEndpoint;
34 | import android.hardware.usb.UsbInterface;
35 | import android.util.Log;
36 |
37 | import java.io.IOException;
38 | import java.lang.reflect.Method;
39 | import java.util.Collections;
40 | import java.util.LinkedHashMap;
41 | import java.util.List;
42 | import java.util.Map;
43 |
44 | public class ProlificSerialDriver implements UsbSerialDriver {
45 |
46 | private final String TAG = ProlificSerialDriver.class.getSimpleName();
47 |
48 | private final UsbDevice mDevice;
49 | private final UsbSerialPort mPort;
50 |
51 | public ProlificSerialDriver(UsbDevice device) {
52 | mDevice = device;
53 | mPort = new ProlificSerialPort(mDevice, 0);
54 | }
55 |
56 | @Override
57 | public List getPorts() {
58 | return Collections.singletonList(mPort);
59 | }
60 |
61 | @Override
62 | public UsbDevice getDevice() {
63 | return mDevice;
64 | }
65 |
66 | class ProlificSerialPort extends CommonUsbSerialPort {
67 |
68 | private static final int USB_READ_TIMEOUT_MILLIS = 1000;
69 | private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
70 |
71 | private static final int USB_RECIP_INTERFACE = 0x01;
72 |
73 | private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
74 | private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
75 |
76 | private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
77 | | UsbConstants.USB_TYPE_VENDOR;
78 |
79 | private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN
80 | | UsbConstants.USB_TYPE_VENDOR;
81 |
82 | private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
83 | | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
84 |
85 | private static final int WRITE_ENDPOINT = 0x02;
86 | private static final int READ_ENDPOINT = 0x83;
87 | private static final int INTERRUPT_ENDPOINT = 0x81;
88 |
89 | private static final int FLUSH_RX_REQUEST = 0x08;
90 | private static final int FLUSH_TX_REQUEST = 0x09;
91 |
92 | private static final int SET_LINE_REQUEST = 0x20;
93 | private static final int SET_CONTROL_REQUEST = 0x22;
94 |
95 | private static final int CONTROL_DTR = 0x01;
96 | private static final int CONTROL_RTS = 0x02;
97 |
98 | private static final int STATUS_FLAG_CD = 0x01;
99 | private static final int STATUS_FLAG_DSR = 0x02;
100 | private static final int STATUS_FLAG_RI = 0x08;
101 | private static final int STATUS_FLAG_CTS = 0x80;
102 |
103 | private static final int STATUS_BUFFER_SIZE = 10;
104 | private static final int STATUS_BYTE_IDX = 8;
105 |
106 | private static final int DEVICE_TYPE_HX = 0;
107 | private static final int DEVICE_TYPE_0 = 1;
108 | private static final int DEVICE_TYPE_1 = 2;
109 |
110 | private int mDeviceType = DEVICE_TYPE_HX;
111 |
112 | private UsbEndpoint mReadEndpoint;
113 | private UsbEndpoint mWriteEndpoint;
114 | private UsbEndpoint mInterruptEndpoint;
115 |
116 | private int mControlLinesValue = 0;
117 |
118 | private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1;
119 |
120 | private int mStatus = 0;
121 | private volatile Thread mReadStatusThread = null;
122 | private final Object mReadStatusThreadLock = new Object();
123 | boolean mStopReadStatusThread = false;
124 | private IOException mReadStatusException = null;
125 |
126 |
127 | public ProlificSerialPort(UsbDevice device, int portNumber) {
128 | super(device, portNumber);
129 | }
130 |
131 | @Override
132 | public UsbSerialDriver getDriver() {
133 | return ProlificSerialDriver.this;
134 | }
135 |
136 | private final byte[] inControlTransfer(int requestType, int request,
137 | int value, int index, int length) throws IOException {
138 | byte[] buffer = new byte[length];
139 | int result = mConnection.controlTransfer(requestType, request, value,
140 | index, buffer, length, USB_READ_TIMEOUT_MILLIS);
141 | if (result != length) {
142 | throw new IOException(
143 | String.format("ControlTransfer with value 0x%x failed: %d",
144 | value, result));
145 | }
146 | return buffer;
147 | }
148 |
149 | private final void outControlTransfer(int requestType, int request,
150 | int value, int index, byte[] data) throws IOException {
151 | int length = (data == null) ? 0 : data.length;
152 | int result = mConnection.controlTransfer(requestType, request, value,
153 | index, data, length, USB_WRITE_TIMEOUT_MILLIS);
154 | if (result != length) {
155 | throw new IOException(
156 | String.format("ControlTransfer with value 0x%x failed: %d",
157 | value, result));
158 | }
159 | }
160 |
161 | private final byte[] vendorIn(int value, int index, int length)
162 | throws IOException {
163 | return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
164 | PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
165 | }
166 |
167 | private final void vendorOut(int value, int index, byte[] data)
168 | throws IOException {
169 | outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
170 | PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
171 | }
172 |
173 | private void resetDevice() throws IOException {
174 | purgeHwBuffers(true, true);
175 | }
176 |
177 | private final void ctrlOut(int request, int value, int index, byte[] data)
178 | throws IOException {
179 | outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
180 | data);
181 | }
182 |
183 | private void doBlackMagic() throws IOException {
184 | vendorIn(0x8484, 0, 1);
185 | vendorOut(0x0404, 0, null);
186 | vendorIn(0x8484, 0, 1);
187 | vendorIn(0x8383, 0, 1);
188 | vendorIn(0x8484, 0, 1);
189 | vendorOut(0x0404, 1, null);
190 | vendorIn(0x8484, 0, 1);
191 | vendorIn(0x8383, 0, 1);
192 | vendorOut(0, 1, null);
193 | vendorOut(1, 0, null);
194 | vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
195 | }
196 |
197 | private void setControlLines(int newControlLinesValue) throws IOException {
198 | ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null);
199 | mControlLinesValue = newControlLinesValue;
200 | }
201 |
202 | private final void readStatusThreadFunction() {
203 | try {
204 | while (!mStopReadStatusThread) {
205 | byte[] buffer = new byte[STATUS_BUFFER_SIZE];
206 | int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint,
207 | buffer,
208 | STATUS_BUFFER_SIZE,
209 | 500);
210 | if (readBytesCount > 0) {
211 | if (readBytesCount == STATUS_BUFFER_SIZE) {
212 | mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
213 | } else {
214 | throw new IOException(
215 | String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d",
216 | STATUS_BUFFER_SIZE,
217 | readBytesCount));
218 | }
219 | }
220 | }
221 | } catch (IOException e) {
222 | mReadStatusException = e;
223 | }
224 | }
225 |
226 | private final int getStatus() throws IOException {
227 | if ((mReadStatusThread == null) && (mReadStatusException == null)) {
228 | synchronized (mReadStatusThreadLock) {
229 | if (mReadStatusThread == null) {
230 | byte[] buffer = new byte[STATUS_BUFFER_SIZE];
231 | int readBytes = mConnection.bulkTransfer(mInterruptEndpoint,
232 | buffer,
233 | STATUS_BUFFER_SIZE,
234 | 100);
235 | if (readBytes != STATUS_BUFFER_SIZE) {
236 | Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status");
237 | } else {
238 | mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
239 | }
240 |
241 | mReadStatusThread = new Thread(new Runnable() {
242 | @Override
243 | public void run() {
244 | readStatusThreadFunction();
245 | }
246 | });
247 | mReadStatusThread.setDaemon(true);
248 | mReadStatusThread.start();
249 | }
250 | }
251 | }
252 |
253 | /* throw and clear an exception which occured in the status read thread */
254 | IOException readStatusException = mReadStatusException;
255 | if (mReadStatusException != null) {
256 | mReadStatusException = null;
257 | throw readStatusException;
258 | }
259 |
260 | return mStatus;
261 | }
262 |
263 | private final boolean testStatusFlag(int flag) throws IOException {
264 | return ((getStatus() & flag) == flag);
265 | }
266 |
267 | @Override
268 | public void open(UsbDeviceConnection connection) throws IOException {
269 | if (mConnection != null) {
270 | throw new IOException("Already open");
271 | }
272 |
273 | UsbInterface usbInterface = mDevice.getInterface(0);
274 |
275 | if (!connection.claimInterface(usbInterface, true)) {
276 | throw new IOException("Error claiming Prolific interface 0");
277 | }
278 |
279 | mConnection = connection;
280 | boolean opened = false;
281 | try {
282 | for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
283 | UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i);
284 |
285 | switch (currentEndpoint.getAddress()) {
286 | case READ_ENDPOINT:
287 | mReadEndpoint = currentEndpoint;
288 | break;
289 |
290 | case WRITE_ENDPOINT:
291 | mWriteEndpoint = currentEndpoint;
292 | break;
293 |
294 | case INTERRUPT_ENDPOINT:
295 | mInterruptEndpoint = currentEndpoint;
296 | break;
297 | }
298 | }
299 |
300 | if (mDevice.getDeviceClass() == 0x02) {
301 | mDeviceType = DEVICE_TYPE_0;
302 | } else {
303 | try {
304 | Method getRawDescriptorsMethod
305 | = mConnection.getClass().getMethod("getRawDescriptors");
306 | byte[] rawDescriptors
307 | = (byte[]) getRawDescriptorsMethod.invoke(mConnection);
308 | byte maxPacketSize0 = rawDescriptors[7];
309 | if (maxPacketSize0 == 64) {
310 | mDeviceType = DEVICE_TYPE_HX;
311 | } else if ((mDevice.getDeviceClass() == 0x00)
312 | || (mDevice.getDeviceClass() == 0xff)) {
313 | mDeviceType = DEVICE_TYPE_1;
314 | } else {
315 | Log.w(TAG, "Could not detect PL2303 subtype, "
316 | + "Assuming that it is a HX device");
317 | mDeviceType = DEVICE_TYPE_HX;
318 | }
319 | } catch (NoSuchMethodException e) {
320 | Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
321 | + "required for PL2303 subtype detection, not "
322 | + "available! Assuming that it is a HX device");
323 | mDeviceType = DEVICE_TYPE_HX;
324 | } catch (Exception e) {
325 | Log.e(TAG, "An unexpected exception occured while trying "
326 | + "to detect PL2303 subtype", e);
327 | }
328 | }
329 |
330 | setControlLines(mControlLinesValue);
331 | resetDevice();
332 |
333 | doBlackMagic();
334 | opened = true;
335 | } finally {
336 | if (!opened) {
337 | mConnection = null;
338 | connection.releaseInterface(usbInterface);
339 | }
340 | }
341 | }
342 |
343 | @Override
344 | public void close() throws IOException {
345 | if (mConnection == null) {
346 | throw new IOException("Already closed");
347 | }
348 | try {
349 | mStopReadStatusThread = true;
350 | synchronized (mReadStatusThreadLock) {
351 | if (mReadStatusThread != null) {
352 | try {
353 | mReadStatusThread.join();
354 | } catch (Exception e) {
355 | Log.w(TAG, "An error occured while waiting for status read thread", e);
356 | }
357 | }
358 | }
359 | resetDevice();
360 | } finally {
361 | try {
362 | mConnection.releaseInterface(mDevice.getInterface(0));
363 | } finally {
364 | mConnection = null;
365 | }
366 | }
367 | }
368 |
369 | @Override
370 | public int read(byte[] dest, int timeoutMillis) throws IOException {
371 | synchronized (mReadBufferLock) {
372 | int readAmt = Math.min(dest.length, mReadBuffer.length);
373 | int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer,
374 | readAmt, timeoutMillis);
375 | if (numBytesRead < 0) {
376 | return 0;
377 | }
378 | System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
379 | return numBytesRead;
380 | }
381 | }
382 |
383 | @Override
384 | public int write(byte[] src, int timeoutMillis) throws IOException {
385 | int offset = 0;
386 |
387 | while (offset < src.length) {
388 | final int writeLength;
389 | final int amtWritten;
390 |
391 | synchronized (mWriteBufferLock) {
392 | final byte[] writeBuffer;
393 |
394 | writeLength = Math.min(src.length - offset, mWriteBuffer.length);
395 | if (offset == 0) {
396 | writeBuffer = src;
397 | } else {
398 | // bulkTransfer does not support offsets, make a copy.
399 | System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
400 | writeBuffer = mWriteBuffer;
401 | }
402 |
403 | amtWritten = mConnection.bulkTransfer(mWriteEndpoint,
404 | writeBuffer, writeLength, timeoutMillis);
405 | }
406 |
407 | if (amtWritten <= 0) {
408 | throw new IOException("Error writing " + writeLength
409 | + " bytes at offset " + offset + " length="
410 | + src.length);
411 | }
412 |
413 | offset += amtWritten;
414 | }
415 | return offset;
416 | }
417 |
418 | @Override
419 | public void setParameters(int baudRate, int dataBits, int stopBits,
420 | int parity) throws IOException {
421 | if ((mBaudRate == baudRate) && (mDataBits == dataBits)
422 | && (mStopBits == stopBits) && (mParity == parity)) {
423 | // Make sure no action is performed if there is nothing to change
424 | return;
425 | }
426 |
427 | byte[] lineRequestData = new byte[7];
428 |
429 | lineRequestData[0] = (byte) (baudRate & 0xff);
430 | lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
431 | lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
432 | lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
433 |
434 | switch (stopBits) {
435 | case STOPBITS_1:
436 | lineRequestData[4] = 0;
437 | break;
438 |
439 | case STOPBITS_1_5:
440 | lineRequestData[4] = 1;
441 | break;
442 |
443 | case STOPBITS_2:
444 | lineRequestData[4] = 2;
445 | break;
446 |
447 | default:
448 | throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
449 | }
450 |
451 | switch (parity) {
452 | case PARITY_NONE:
453 | lineRequestData[5] = 0;
454 | break;
455 |
456 | case PARITY_ODD:
457 | lineRequestData[5] = 1;
458 | break;
459 |
460 | case PARITY_MARK:
461 | lineRequestData[5] = 3;
462 | break;
463 |
464 | case PARITY_SPACE:
465 | lineRequestData[5] = 4;
466 | break;
467 |
468 | default:
469 | throw new IllegalArgumentException("Unknown parity value: " + parity);
470 | }
471 |
472 | lineRequestData[6] = (byte) dataBits;
473 |
474 | ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
475 |
476 | resetDevice();
477 |
478 | mBaudRate = baudRate;
479 | mDataBits = dataBits;
480 | mStopBits = stopBits;
481 | mParity = parity;
482 | }
483 |
484 | @Override
485 | public boolean getCD() throws IOException {
486 | return testStatusFlag(STATUS_FLAG_CD);
487 | }
488 |
489 | @Override
490 | public boolean getCTS() throws IOException {
491 | return testStatusFlag(STATUS_FLAG_CTS);
492 | }
493 |
494 | @Override
495 | public boolean getDSR() throws IOException {
496 | return testStatusFlag(STATUS_FLAG_DSR);
497 | }
498 |
499 | @Override
500 | public boolean getDTR() throws IOException {
501 | return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR);
502 | }
503 |
504 | @Override
505 | public void setDTR(boolean value) throws IOException {
506 | int newControlLinesValue;
507 | if (value) {
508 | newControlLinesValue = mControlLinesValue | CONTROL_DTR;
509 | } else {
510 | newControlLinesValue = mControlLinesValue & ~CONTROL_DTR;
511 | }
512 | setControlLines(newControlLinesValue);
513 | }
514 |
515 | @Override
516 | public boolean getRI() throws IOException {
517 | return testStatusFlag(STATUS_FLAG_RI);
518 | }
519 |
520 | @Override
521 | public boolean getRTS() throws IOException {
522 | return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS);
523 | }
524 |
525 | @Override
526 | public void setRTS(boolean value) throws IOException {
527 | int newControlLinesValue;
528 | if (value) {
529 | newControlLinesValue = mControlLinesValue | CONTROL_RTS;
530 | } else {
531 | newControlLinesValue = mControlLinesValue & ~CONTROL_RTS;
532 | }
533 | setControlLines(newControlLinesValue);
534 | }
535 |
536 | @Override
537 | public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
538 | if (purgeReadBuffers) {
539 | vendorOut(FLUSH_RX_REQUEST, 0, null);
540 | }
541 |
542 | if (purgeWriteBuffers) {
543 | vendorOut(FLUSH_TX_REQUEST, 0, null);
544 | }
545 |
546 | return purgeReadBuffers || purgeWriteBuffers;
547 | }
548 | }
549 |
550 | public static Map getSupportedDevices() {
551 | final Map supportedDevices = new LinkedHashMap();
552 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_PROLIFIC),
553 | new int[] { UsbId.PROLIFIC_PL2303, });
554 | return supportedDevices;
555 | }
556 | }
557 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/UsbId.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | /**
25 | * Registry of USB vendor/product ID constants.
26 | *
27 | * Culled from various sources; see usb.ids for one listing.
29 | *
30 | * @author mike wakerly (opensource@hoho.com)
31 | */
32 | public final class UsbId {
33 |
34 | public static final int VENDOR_FTDI = 0x0403;
35 | public static final int FTDI_FT232R = 0x6001;
36 | public static final int FTDI_FT231X = 0x6015;
37 |
38 | public static final int VENDOR_ATMEL = 0x03EB;
39 | public static final int ATMEL_LUFA_CDC_DEMO_APP = 0x2044;
40 |
41 | public static final int VENDOR_ARDUINO = 0x2341;
42 | public static final int ARDUINO_UNO = 0x0001;
43 | public static final int ARDUINO_MEGA_2560 = 0x0010;
44 | public static final int ARDUINO_SERIAL_ADAPTER = 0x003b;
45 | public static final int ARDUINO_MEGA_ADK = 0x003f;
46 | public static final int ARDUINO_MEGA_2560_R3 = 0x0042;
47 | public static final int ARDUINO_UNO_R3 = 0x0043;
48 | public static final int ARDUINO_MEGA_ADK_R3 = 0x0044;
49 | public static final int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044;
50 | public static final int ARDUINO_LEONARDO = 0x8036;
51 |
52 | public static final int VENDOR_VAN_OOIJEN_TECH = 0x16c0;
53 | public static final int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483;
54 |
55 | public static final int VENDOR_LEAFLABS = 0x1eaf;
56 | public static final int LEAFLABS_MAPLE = 0x0004;
57 |
58 | public static final int VENDOR_SILABS = 0x10c4;
59 | public static final int SILABS_CP2102 = 0xea60;
60 | public static final int SILABS_CP2105 = 0xea70;
61 | public static final int SILABS_CP2108 = 0xea71;
62 | public static final int SILABS_CP2110 = 0xea80;
63 |
64 | public static final int VENDOR_PROLIFIC = 0x067b;
65 | public static final int PROLIFIC_PL2303 = 0x2303;
66 |
67 | private UsbId() {
68 | throw new IllegalAccessError("Non-instantiable class.");
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbDevice;
25 |
26 | import java.util.List;
27 |
28 | /**
29 | *
30 | * @author mike wakerly (opensource@hoho.com)
31 | */
32 | public interface UsbSerialDriver {
33 |
34 | /**
35 | * Returns the raw {@link UsbDevice} backing this port.
36 | *
37 | * @return the device
38 | */
39 | public UsbDevice getDevice();
40 |
41 | /**
42 | * Returns all available ports for this device. This list must have at least
43 | * one entry.
44 | *
45 | * @return the ports
46 | */
47 | public List getPorts();
48 | }
49 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/UsbSerialPort.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbDeviceConnection;
25 | import android.hardware.usb.UsbManager;
26 |
27 | import java.io.IOException;
28 |
29 | /**
30 | * Interface for a single serial port.
31 | *
32 | * @author mike wakerly (opensource@hoho.com)
33 | */
34 | public interface UsbSerialPort {
35 |
36 | /** 5 data bits. */
37 | public static final int DATABITS_5 = 5;
38 |
39 | /** 6 data bits. */
40 | public static final int DATABITS_6 = 6;
41 |
42 | /** 7 data bits. */
43 | public static final int DATABITS_7 = 7;
44 |
45 | /** 8 data bits. */
46 | public static final int DATABITS_8 = 8;
47 |
48 | /** No flow control. */
49 | public static final int FLOWCONTROL_NONE = 0;
50 |
51 | /** RTS/CTS input flow control. */
52 | public static final int FLOWCONTROL_RTSCTS_IN = 1;
53 |
54 | /** RTS/CTS output flow control. */
55 | public static final int FLOWCONTROL_RTSCTS_OUT = 2;
56 |
57 | /** XON/XOFF input flow control. */
58 | public static final int FLOWCONTROL_XONXOFF_IN = 4;
59 |
60 | /** XON/XOFF output flow control. */
61 | public static final int FLOWCONTROL_XONXOFF_OUT = 8;
62 |
63 | /** No parity. */
64 | public static final int PARITY_NONE = 0;
65 |
66 | /** Odd parity. */
67 | public static final int PARITY_ODD = 1;
68 |
69 | /** Even parity. */
70 | public static final int PARITY_EVEN = 2;
71 |
72 | /** Mark parity. */
73 | public static final int PARITY_MARK = 3;
74 |
75 | /** Space parity. */
76 | public static final int PARITY_SPACE = 4;
77 |
78 | /** 1 stop bit. */
79 | public static final int STOPBITS_1 = 1;
80 |
81 | /** 1.5 stop bits. */
82 | public static final int STOPBITS_1_5 = 3;
83 |
84 | /** 2 stop bits. */
85 | public static final int STOPBITS_2 = 2;
86 |
87 | public UsbSerialDriver getDriver();
88 |
89 | /**
90 | * Port number within driver.
91 | */
92 | public int getPortNumber();
93 |
94 | /**
95 | * The serial number of the underlying UsbDeviceConnection, or {@code null}.
96 | */
97 | public String getSerial();
98 |
99 | /**
100 | * Opens and initializes the port. Upon success, caller must ensure that
101 | * {@link #close()} is eventually called.
102 | *
103 | * @param connection an open device connection, acquired with
104 | * {@link UsbManager#openDevice(android.hardware.usb.UsbDevice)}
105 | * @throws IOException on error opening or initializing the port.
106 | */
107 | public void open(UsbDeviceConnection connection) throws IOException;
108 |
109 | /**
110 | * Closes the port.
111 | *
112 | * @throws IOException on error closing the port.
113 | */
114 | public void close() throws IOException;
115 |
116 | /**
117 | * Reads as many bytes as possible into the destination buffer.
118 | *
119 | * @param dest the destination byte buffer
120 | * @param timeoutMillis the timeout for reading
121 | * @return the actual number of bytes read
122 | * @throws IOException if an error occurred during reading
123 | */
124 | public int read(final byte[] dest, final int timeoutMillis) throws IOException;
125 |
126 | /**
127 | * Writes as many bytes as possible from the source buffer.
128 | *
129 | * @param src the source byte buffer
130 | * @param timeoutMillis the timeout for writing
131 | * @return the actual number of bytes written
132 | * @throws IOException if an error occurred during writing
133 | */
134 | public int write(final byte[] src, final int timeoutMillis) throws IOException;
135 |
136 | /**
137 | * Sets various serial port parameters.
138 | *
139 | * @param baudRate baud rate as an integer, for example {@code 115200}.
140 | * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6},
141 | * {@link #DATABITS_7}, or {@link #DATABITS_8}.
142 | * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or
143 | * {@link #STOPBITS_2}.
144 | * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD},
145 | * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or
146 | * {@link #PARITY_SPACE}.
147 | * @throws IOException on error setting the port parameters
148 | */
149 | public void setParameters(
150 | int baudRate, int dataBits, int stopBits, int parity) throws IOException;
151 |
152 | /**
153 | * Gets the CD (Carrier Detect) bit from the underlying UART.
154 | *
155 | * @return the current state, or {@code false} if not supported.
156 | * @throws IOException if an error occurred during reading
157 | */
158 | public boolean getCD() throws IOException;
159 |
160 | /**
161 | * Gets the CTS (Clear To Send) bit from the underlying UART.
162 | *
163 | * @return the current state, or {@code false} if not supported.
164 | * @throws IOException if an error occurred during reading
165 | */
166 | public boolean getCTS() throws IOException;
167 |
168 | /**
169 | * Gets the DSR (Data Set Ready) bit from the underlying UART.
170 | *
171 | * @return the current state, or {@code false} if not supported.
172 | * @throws IOException if an error occurred during reading
173 | */
174 | public boolean getDSR() throws IOException;
175 |
176 | /**
177 | * Gets the DTR (Data Terminal Ready) bit from the underlying UART.
178 | *
179 | * @return the current state, or {@code false} if not supported.
180 | * @throws IOException if an error occurred during reading
181 | */
182 | public boolean getDTR() throws IOException;
183 |
184 | /**
185 | * Sets the DTR (Data Terminal Ready) bit on the underlying UART, if
186 | * supported.
187 | *
188 | * @param value the value to set
189 | * @throws IOException if an error occurred during writing
190 | */
191 | public void setDTR(boolean value) throws IOException;
192 |
193 | /**
194 | * Gets the RI (Ring Indicator) bit from the underlying UART.
195 | *
196 | * @return the current state, or {@code false} if not supported.
197 | * @throws IOException if an error occurred during reading
198 | */
199 | public boolean getRI() throws IOException;
200 |
201 | /**
202 | * Gets the RTS (Request To Send) bit from the underlying UART.
203 | *
204 | * @return the current state, or {@code false} if not supported.
205 | * @throws IOException if an error occurred during reading
206 | */
207 | public boolean getRTS() throws IOException;
208 |
209 | /**
210 | * Sets the RTS (Request To Send) bit on the underlying UART, if
211 | * supported.
212 | *
213 | * @param value the value to set
214 | * @throws IOException if an error occurred during writing
215 | */
216 | public void setRTS(boolean value) throws IOException;
217 |
218 | /**
219 | * Flush non-transmitted output data and / or non-read input data
220 | * @param flushRX {@code true} to flush non-transmitted output data
221 | * @param flushTX {@code true} to flush non-read input data
222 | * @return {@code true} if the operation was successful, or
223 | * {@code false} if the operation is not supported by the driver or device
224 | * @throws IOException if an error occurred during flush
225 | */
226 | public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException;
227 |
228 | }
229 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/UsbSerialProber.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.driver;
23 |
24 | import android.hardware.usb.UsbDevice;
25 | import android.hardware.usb.UsbManager;
26 |
27 | import java.lang.reflect.Constructor;
28 | import java.lang.reflect.InvocationTargetException;
29 | import java.util.ArrayList;
30 | import java.util.List;
31 |
32 | /**
33 | *
34 | * @author mike wakerly (opensource@hoho.com)
35 | */
36 | public class UsbSerialProber {
37 |
38 | private final ProbeTable mProbeTable;
39 |
40 | public UsbSerialProber(ProbeTable probeTable) {
41 | mProbeTable = probeTable;
42 | }
43 |
44 | public static UsbSerialProber getDefaultProber() {
45 | return new UsbSerialProber(getDefaultProbeTable());
46 | }
47 |
48 | public static ProbeTable getDefaultProbeTable() {
49 | final ProbeTable probeTable = new ProbeTable();
50 | probeTable.addDriver(CdcAcmSerialDriver.class);
51 | probeTable.addDriver(Cp21xxSerialDriver.class);
52 | probeTable.addDriver(FtdiSerialDriver.class);
53 | probeTable.addDriver(ProlificSerialDriver.class);
54 | return probeTable;
55 | }
56 |
57 | /**
58 | * Finds and builds all possible {@link UsbSerialDriver UsbSerialDrivers}
59 | * from the currently-attached {@link UsbDevice} hierarchy. This method does
60 | * not require permission from the Android USB system, since it does not
61 | * open any of the devices.
62 | *
63 | * @param usbManager
64 | * @return a list, possibly empty, of all compatible drivers
65 | */
66 | public List findAllDrivers(final UsbManager usbManager) {
67 | final List result = new ArrayList();
68 |
69 | for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) {
70 | final UsbSerialDriver driver = probeDevice(usbDevice);
71 | if (driver != null) {
72 | result.add(driver);
73 | }
74 | }
75 | return result;
76 | }
77 |
78 | /**
79 | * Probes a single device for a compatible driver.
80 | *
81 | * @param usbDevice the usb device to probe
82 | * @return a new {@link UsbSerialDriver} compatible with this device, or
83 | * {@code null} if none available.
84 | */
85 | public UsbSerialDriver probeDevice(final UsbDevice usbDevice) {
86 | final int vendorId = usbDevice.getVendorId();
87 | final int productId = usbDevice.getProductId();
88 |
89 | final Class extends UsbSerialDriver> driverClass =
90 | mProbeTable.findDriver(vendorId, productId);
91 | if (driverClass != null) {
92 | final UsbSerialDriver driver;
93 | try {
94 | final Constructor extends UsbSerialDriver> ctor =
95 | driverClass.getConstructor(UsbDevice.class);
96 | driver = ctor.newInstance(usbDevice);
97 | } catch (NoSuchMethodException e) {
98 | throw new RuntimeException(e);
99 | } catch (IllegalArgumentException e) {
100 | throw new RuntimeException(e);
101 | } catch (InstantiationException e) {
102 | throw new RuntimeException(e);
103 | } catch (IllegalAccessException e) {
104 | throw new RuntimeException(e);
105 | } catch (InvocationTargetException e) {
106 | throw new RuntimeException(e);
107 | }
108 | return driver;
109 | }
110 | return null;
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/driver/UsbSerialRuntimeException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 Google Inc.
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | */
19 |
20 | package com.hoho.android.usbserial.driver;
21 |
22 | /**
23 | * Generic unchecked exception for the usbserial package.
24 | *
25 | * @author mike wakerly (opensource@hoho.com)
26 | */
27 | @SuppressWarnings("serial")
28 | public class UsbSerialRuntimeException extends RuntimeException {
29 |
30 | public UsbSerialRuntimeException() {
31 | super();
32 | }
33 |
34 | public UsbSerialRuntimeException(String detailMessage, Throwable throwable) {
35 | super(detailMessage, throwable);
36 | }
37 |
38 | public UsbSerialRuntimeException(String detailMessage) {
39 | super(detailMessage);
40 | }
41 |
42 | public UsbSerialRuntimeException(Throwable throwable) {
43 | super(throwable);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/util/HexDump.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2006 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hoho.android.usbserial.util;
18 |
19 | /**
20 | * Clone of Android's HexDump class, for use in debugging. Cosmetic changes
21 | * only.
22 | */
23 | public class HexDump {
24 | private final static char[] HEX_DIGITS = {
25 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
26 | };
27 |
28 | public static String dumpHexString(byte[] array) {
29 | return dumpHexString(array, 0, array.length);
30 | }
31 |
32 | public static String dumpHexString(byte[] array, int offset, int length) {
33 | StringBuilder result = new StringBuilder();
34 |
35 | byte[] line = new byte[16];
36 | int lineIndex = 0;
37 |
38 | result.append("\n0x");
39 | result.append(toHexString(offset));
40 |
41 | for (int i = offset; i < offset + length; i++) {
42 | if (lineIndex == 16) {
43 | result.append(" ");
44 |
45 | for (int j = 0; j < 16; j++) {
46 | if (line[j] > ' ' && line[j] < '~') {
47 | result.append(new String(line, j, 1));
48 | } else {
49 | result.append(".");
50 | }
51 | }
52 |
53 | result.append("\n0x");
54 | result.append(toHexString(i));
55 | lineIndex = 0;
56 | }
57 |
58 | byte b = array[i];
59 | result.append(" ");
60 | result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
61 | result.append(HEX_DIGITS[b & 0x0F]);
62 |
63 | line[lineIndex++] = b;
64 | }
65 |
66 | if (lineIndex != 16) {
67 | int count = (16 - lineIndex) * 3;
68 | count++;
69 | for (int i = 0; i < count; i++) {
70 | result.append(" ");
71 | }
72 |
73 | for (int i = 0; i < lineIndex; i++) {
74 | if (line[i] > ' ' && line[i] < '~') {
75 | result.append(new String(line, i, 1));
76 | } else {
77 | result.append(".");
78 | }
79 | }
80 | }
81 |
82 | return result.toString();
83 | }
84 |
85 | public static String toHexString(byte b) {
86 | return toHexString(toByteArray(b));
87 | }
88 |
89 | public static String toHexString(byte[] array) {
90 | return toHexString(array, 0, array.length);
91 | }
92 |
93 | public static String toHexString(byte[] array, int offset, int length) {
94 | char[] buf = new char[length * 2];
95 |
96 | int bufIndex = 0;
97 | for (int i = offset; i < offset + length; i++) {
98 | byte b = array[i];
99 | buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
100 | buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
101 | }
102 |
103 | return new String(buf);
104 | }
105 |
106 | public static String toHexString(int i) {
107 | return toHexString(toByteArray(i));
108 | }
109 |
110 | public static String toHexString(short i) {
111 | return toHexString(toByteArray(i));
112 | }
113 |
114 | public static byte[] toByteArray(byte b) {
115 | byte[] array = new byte[1];
116 | array[0] = b;
117 | return array;
118 | }
119 |
120 | public static byte[] toByteArray(int i) {
121 | byte[] array = new byte[4];
122 |
123 | array[3] = (byte) (i & 0xFF);
124 | array[2] = (byte) ((i >> 8) & 0xFF);
125 | array[1] = (byte) ((i >> 16) & 0xFF);
126 | array[0] = (byte) ((i >> 24) & 0xFF);
127 |
128 | return array;
129 | }
130 |
131 | public static byte[] toByteArray(short i) {
132 | byte[] array = new byte[2];
133 |
134 | array[1] = (byte) (i & 0xFF);
135 | array[0] = (byte) ((i >> 8) & 0xFF);
136 |
137 | return array;
138 | }
139 |
140 | private static int toByte(char c) {
141 | if (c >= '0' && c <= '9')
142 | return (c - '0');
143 | if (c >= 'A' && c <= 'F')
144 | return (c - 'A' + 10);
145 | if (c >= 'a' && c <= 'f')
146 | return (c - 'a' + 10);
147 |
148 | throw new RuntimeException("Invalid hex char '" + c + "'");
149 | }
150 |
151 | public static byte[] hexStringToByteArray(String hexString) {
152 | int length = hexString.length();
153 | byte[] buffer = new byte[length / 2];
154 |
155 | for (int i = 0; i < length; i += 2) {
156 | buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString
157 | .charAt(i + 1)));
158 | }
159 |
160 | return buffer;
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2013 Google Inc.
2 | * Copyright 2013 mike wakerly
3 | *
4 | * This library is free software; you can redistribute it and/or
5 | * modify it under the terms of the GNU Lesser General Public
6 | * License as published by the Free Software Foundation; either
7 | * version 2.1 of the License, or (at your option) any later version.
8 | *
9 | * This library is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this library; if not, write to the Free Software
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 | * USA.
18 | *
19 | * Project home page: https://github.com/mik3y/usb-serial-for-android
20 | */
21 |
22 | package com.hoho.android.usbserial.util;
23 |
24 | import android.hardware.usb.UsbRequest;
25 | import android.util.Log;
26 |
27 | import com.hoho.android.usbserial.driver.UsbSerialPort;
28 |
29 | import java.io.IOException;
30 | import java.nio.ByteBuffer;
31 |
32 | /**
33 | * Utility class which services a {@link UsbSerialPort} in its {@link #run()}
34 | * method.
35 | *
36 | * @author mike wakerly (opensource@hoho.com)
37 | */
38 | public class SerialInputOutputManager implements Runnable {
39 |
40 | private static final String TAG = SerialInputOutputManager.class.getSimpleName();
41 | private static final boolean DEBUG = true;
42 |
43 | private static final int READ_WAIT_MILLIS = 200;
44 | private static final int BUFSIZ = 4096;
45 |
46 | private final UsbSerialPort mDriver;
47 |
48 | private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ);
49 |
50 | // Synchronized by 'mWriteBuffer'
51 | private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ);
52 |
53 | private enum State {
54 | STOPPED,
55 | RUNNING,
56 | STOPPING
57 | }
58 |
59 | // Synchronized by 'this'
60 | private State mState = State.STOPPED;
61 |
62 | // Synchronized by 'this'
63 | private Listener mListener;
64 |
65 | public interface Listener {
66 | /**
67 | * Called when new incoming data is available.
68 | */
69 | public void onNewData(byte[] data);
70 |
71 | /**
72 | * Called when {@link SerialInputOutputManager#run()} aborts due to an
73 | * error.
74 | */
75 | public void onRunError(Exception e);
76 | }
77 |
78 | /**
79 | * Creates a new instance with no listener.
80 | */
81 | public SerialInputOutputManager(UsbSerialPort driver) {
82 | this(driver, null);
83 | }
84 |
85 | /**
86 | * Creates a new instance with the provided listener.
87 | */
88 | public SerialInputOutputManager(UsbSerialPort driver, Listener listener) {
89 | mDriver = driver;
90 | mListener = listener;
91 | }
92 |
93 | public synchronized void setListener(Listener listener) {
94 | mListener = listener;
95 | }
96 |
97 | public synchronized Listener getListener() {
98 | return mListener;
99 | }
100 |
101 | public void writeAsync(byte[] data) {
102 | synchronized (mWriteBuffer) {
103 | mWriteBuffer.put(data);
104 | }
105 | }
106 |
107 | public synchronized void stop() {
108 | if (getState() == State.RUNNING) {
109 | Log.i(TAG, "Stop requested");
110 | mState = State.STOPPING;
111 | }
112 | }
113 |
114 | private synchronized State getState() {
115 | return mState;
116 | }
117 |
118 | /**
119 | * Continuously services the read and write buffers until {@link #stop()} is
120 | * called, or until a driver exception is raised.
121 | *
122 | * NOTE(mikey): Uses inefficient read/write-with-timeout.
123 | * TODO(mikey): Read asynchronously with {@link UsbRequest#queue(ByteBuffer, int)}
124 | */
125 | @Override
126 | public void run() {
127 | synchronized (this) {
128 | if (getState() != State.STOPPED) {
129 | throw new IllegalStateException("Already running.");
130 | }
131 | mState = State.RUNNING;
132 | }
133 |
134 | Log.i(TAG, "Running ..");
135 | try {
136 | while (true) {
137 | if (getState() != State.RUNNING) {
138 | Log.i(TAG, "Stopping mState=" + getState());
139 | break;
140 | }
141 | step();
142 | }
143 | } catch (Exception e) {
144 | Log.w(TAG, "Run ending due to exception: " + e.getMessage(), e);
145 | final Listener listener = getListener();
146 | if (listener != null) {
147 | listener.onRunError(e);
148 | }
149 | } finally {
150 | synchronized (this) {
151 | mState = State.STOPPED;
152 | Log.i(TAG, "Stopped.");
153 | }
154 | }
155 | }
156 |
157 | private void step() throws IOException {
158 | // Handle incoming data.
159 | int len = mDriver.read(mReadBuffer.array(), READ_WAIT_MILLIS);
160 | if (len > 0) {
161 | if (DEBUG) Log.d(TAG, "Read data len=" + len);
162 | final Listener listener = getListener();
163 | if (listener != null) {
164 | final byte[] data = new byte[len];
165 | mReadBuffer.get(data, 0, len);
166 | listener.onNewData(data);
167 | }
168 | mReadBuffer.clear();
169 | }
170 |
171 | // Handle outgoing data.
172 | byte[] outBuff = null;
173 | synchronized (mWriteBuffer) {
174 | len = mWriteBuffer.position();
175 | if (len > 0) {
176 | outBuff = new byte[len];
177 | mWriteBuffer.rewind();
178 | mWriteBuffer.get(outBuff, 0, len);
179 | mWriteBuffer.clear();
180 | }
181 | }
182 | if (outBuff != null) {
183 | if (DEBUG) {
184 | Log.d(TAG, "Writing data len=" + len);
185 | }
186 | mDriver.write(outBuff, READ_WAIT_MILLIS);
187 | }
188 | }
189 |
190 | }
191 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/SdrSerialDriver.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android;
2 |
3 | import java.io.IOException;
4 | import java.util.Collections;
5 | import java.util.LinkedHashMap;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | import android.hardware.usb.UsbDevice;
10 | import android.hardware.usb.UsbDeviceConnection;
11 |
12 | import com.hoho.android.usbserial.driver.CommonUsbSerialPort;
13 | import com.hoho.android.usbserial.driver.UsbSerialDriver;
14 | import com.hoho.android.usbserial.driver.UsbSerialPort;
15 |
16 | public class SdrSerialDriver implements UsbSerialDriver {
17 |
18 | private class SdrSerialPort extends CommonUsbSerialPort {
19 |
20 | public SdrSerialPort(UsbDevice device, int portNumber) {
21 | super(device, portNumber);
22 | }
23 |
24 | @Override
25 | public void close() throws IOException {
26 | }
27 |
28 | @Override
29 | public boolean getCD() throws IOException {
30 | return false;
31 | }
32 |
33 | @Override
34 | public boolean getCTS() throws IOException {
35 | return false;
36 | }
37 |
38 | @Override
39 | public UsbSerialDriver getDriver() {
40 | return null;
41 | }
42 |
43 | @Override
44 | public boolean getDSR() throws IOException {
45 | return false;
46 | }
47 |
48 | @Override
49 | public boolean getDTR() throws IOException {
50 | return false;
51 | }
52 |
53 | @Override
54 | public boolean getRI() throws IOException {
55 | return false;
56 | }
57 |
58 | @Override
59 | public boolean getRTS() throws IOException {
60 | return false;
61 | }
62 |
63 | @Override
64 | public void open(UsbDeviceConnection connection) throws IOException {
65 | }
66 |
67 | @Override
68 | public int read(byte[] dest, int timeoutMillis) throws IOException {
69 | return 0;
70 | }
71 |
72 | @Override
73 | public void setDTR(boolean value) throws IOException {
74 | }
75 |
76 | @Override
77 | public void setParameters(int baudRate, int dataBits, int stopBits,
78 | int parity) throws IOException {
79 | }
80 |
81 | @Override
82 | public void setRTS(boolean value) throws IOException {
83 | }
84 |
85 | @Override
86 | public int write(byte[] src, int timeoutMillis) throws IOException {
87 | return 0;
88 | }
89 | }
90 |
91 | public static Map getSupportedDevices() {
92 | final Map supportedDevices = new LinkedHashMap();
93 |
94 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_KYE),
95 | new int[] { SdrUsbId.KYE_RTL2832_707F });
96 |
97 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_RTL), new int[] {
98 | SdrUsbId.RTL_RTL2832, SdrUsbId.RTL_RTL2838 });
99 |
100 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_TERRATEC),
101 | new int[] { SdrUsbId.TERRATEC_RTL2838_A9,
102 | SdrUsbId.TERRATEC_RTL2838_B3,
103 | SdrUsbId.TERRATEC_RTL2838_B4,
104 | SdrUsbId.TERRATEC_RTL2838_B7,
105 | SdrUsbId.TERRATEC_RTL2838_C6,
106 | SdrUsbId.TERRATEC_RTL2838_D3,
107 | SdrUsbId.TERRATEC_RTL2838_D7,
108 | SdrUsbId.TERRATEC_RTL2838_E0 });
109 |
110 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_COMPRO),
111 | new int[] { SdrUsbId.COMPRO_620, SdrUsbId.COMPRO_650,
112 | SdrUsbId.COMPRO_680 });
113 |
114 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_AFATECH),
115 | new int[] { SdrUsbId.AFATECH_RTL2838_D393,
116 | SdrUsbId.AFATECH_RTL2838_D394,
117 | SdrUsbId.AFATECH_RTL2838_D395,
118 | SdrUsbId.AFATECH_RTL2838_D395,
119 | SdrUsbId.AFATECH_RTL2838_D396,
120 | SdrUsbId.AFATECH_RTL2838_D397,
121 | SdrUsbId.AFATECH_RTL2838_D398,
122 | SdrUsbId.AFATECH_RTL2838_D39D,
123 | SdrUsbId.AFATECH_RTL2838_D3A4 });
124 |
125 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_DEXATEC),
126 | new int[] { SdrUsbId.DEXATEC_1101, SdrUsbId.DEXATEC_1102,
127 | SdrUsbId.DEXATEC_1103 });
128 |
129 | supportedDevices.put(Integer.valueOf(SdrUsbId.VENDOR_GTEK), new int[] {
130 | SdrUsbId.GTEK_RTL2838_B803, SdrUsbId.GTEK_RTL2838_C803,
131 | SdrUsbId.GTEK_RTL2838_D286, SdrUsbId.GTEK_RTL2838_D803 });
132 |
133 | return supportedDevices;
134 | }
135 |
136 | private final UsbDevice mDevice;
137 |
138 | private final UsbSerialPort mPort;
139 |
140 | public SdrSerialDriver(UsbDevice device) {
141 | mDevice = device;
142 | mPort = new SdrSerialPort(mDevice, 0);
143 | }
144 |
145 | @Override
146 | public UsbDevice getDevice() {
147 | return mDevice;
148 | }
149 |
150 | @Override
151 | public List getPorts() {
152 | return Collections.singletonList(mPort);
153 | }
154 | }
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/SdrSerialDriverOrig.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android;
2 |
3 | import java.io.IOException;
4 | import java.util.LinkedHashMap;
5 | import java.util.Map;
6 |
7 | //import android.hardware.usb.UsbConstants;
8 | import android.hardware.usb.UsbConstants;
9 | import android.hardware.usb.UsbDevice;
10 | import android.hardware.usb.UsbDeviceConnection;
11 | import android.hardware.usb.UsbEndpoint;
12 | import android.hardware.usb.UsbInterface;
13 | import android.util.Log;
14 |
15 | import com.hoho.android.usbserial.driver.CommonUsbSerialDriver;
16 | import com.hoho.android.usbserial.driver.UsbId;
17 | import com.rtlsdr.android.tuners.E4K;
18 | import com.rtlsdr.android.tuners.FC0012;
19 | import com.rtlsdr.android.tuners.FC0013;
20 | import com.rtlsdr.android.tuners.FC2580;
21 | import com.rtlsdr.android.tuners.IRtlSdrTuner;
22 | import com.rtlsdr.android.tuners.R820T;
23 |
24 | public class SdrSerialDriverOrig extends CommonUsbSerialDriver {
25 | private static final String TAG = SdrSerialDriverOrig.class.getSimpleName();
26 | static IRtlSdrTuner myTuner = null;
27 | boolean set_gain_mode = true;
28 | /*
29 | * private static final int DEFAULT_BAUD_RATE = 9600;
30 | *
31 | * private static final int DEFAULT_BUF_LENGTH = 512;//(16 * 16384); private
32 | * static final char MESSAGEGO = 253; private static final char OVERWRITE =
33 | * 254; private static final char BADSAMPLE = 255;
34 | */
35 | private final int MODES_DEFAULT_RATE = 2000000;
36 | private final int MODES_DEFAULT_FREQ = 1090000000;
37 | private final int MODES_AUTO_GAIN = -100; /* Use automatic gain. */
38 | private final int MODES_MAX_GAIN = 999999; /* Use max available gain. */
39 | // /private final long ADSB_FREQ = 1090000000;
40 | // private final int AUTO_GAIN = -100;
41 | // private final long ADSB_RATE = 2000000;
42 | private int gain = MODES_MAX_GAIN;// AUTO_GAIN;
43 | private boolean enable_agc = false;
44 | private long freq = MODES_DEFAULT_FREQ;
45 | // Buffersizes
46 | // private static final int MODES_PREAMBLE_US = 8;
47 | // private static final int MODES_LONG_MSG_BITS =112;
48 | // private static final int MODES_FULL_LEN
49 | // =(MODES_PREAMBLE_US+MODES_LONG_MSG_BITS);
50 | // private static final int MODES_DATA_LEN = (16*16384); /* 256k */
51 | // private static final int BUFSIZ = MODES_DATA_LEN + (MODES_FULL_LEN-1)*4;
52 |
53 | // private byte [] input = new byte[BUFSIZ];
54 | // private static char[] mag = new char[BUFSIZ *2];
55 |
56 | // private int [] adsb_frame = new int[14];
57 | // private final int preamble_len = 16;
58 | // private final int long_frame = 112;
59 | // private final int char_frame = 56;
60 | // private double quality = 1.0;
61 | // private int allowed_errors = 5;
62 |
63 | private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;// was 5000
64 |
65 | /*
66 | * Configuration Request Types
67 | */
68 | private static final int REQTYPE_HOST_TO_DEVICE = 0x41;
69 | // private static final int REQTYPE_DEVICE_TO_HOST = 0x80;
70 |
71 | /** In: device-to-host */
72 | private static final int LIBUSB_ENDPOINT_IN = 0x80;
73 |
74 | /** Out: host-to-device */
75 | private static final int LIBUSB_ENDPOINT_OUT = 0x00;
76 |
77 | /** Standard */
78 | // private static final int LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5);
79 |
80 | /** Class */
81 | // private static final int LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5);
82 |
83 | /** Vendor */
84 | private static final int LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5);
85 |
86 | /** Reserved */
87 | // private static final int LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5);
88 |
89 | private static final byte CTRL_IN = (byte) (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN);
90 | private static final byte CTRL_OUT = (byte) (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT);
91 |
92 | // private static final int DEFAULT_SAMPLE_RATE = 2048000;
93 | // private static final int DEFAULT_ASYNC_BUF_NUMBER = 32;
94 | // private static final int DEFAULT_BUF_LENGTH = (16 * 16384);
95 | // private static final int MINIMAL_BUF_LENGTH = 512;
96 | // static final int MAXIMAL_BUF_LENGTH = (256 * 16384);
97 |
98 | // private static final int DEFAULT_BUF_NUMBER = 32;
99 | // private static final int DEFAULT_BUF_LENGTH = (16 * 32 * 512);
100 |
101 | private static final int DEF_RTL_XTAL_FREQ = 28800000;
102 | private static final int MIN_RTL_XTAL_FREQ = (DEF_RTL_XTAL_FREQ - 1000);
103 | private static final int MAX_RTL_XTAL_FREQ = (DEF_RTL_XTAL_FREQ + 1000);
104 |
105 | private static final int MAX_SAMP_RATE = 3200000;
106 |
107 | // private static final int CTRL_TIMEOUT = 300;
108 | private static final int BULK_TIMEOUT = 0;
109 | private static final char EEPROM_ADDR = 0xa0;
110 |
111 | private static final char USB_SYSCTL = 0x2000;
112 | // private static final char USB_CTRL = 0x2010;
113 | // private static final char USB_STAT = 0x2014;
114 | // private static final char USB_EPA_CFG = 0x2144;
115 | private static final char USB_EPA_CTL = 0x2148;
116 | private static final char USB_EPA_MAXPKT = 0x2158;
117 | // private static final char USB_EPA_MAXPKT_2 = 0x215a;
118 | // private static final char USB_EPA_FIFO_CFG = 0x2160;
119 |
120 | private static final char DEMOD_CTL = 0x3000;
121 | private static final char GPO = 0x3001;
122 | // private static final char GPI = 0x3002;
123 | private static final char GPOE = 0x3003;
124 | private static final char GPD = 0x3004;
125 | // private static final char SYSINTE = 0x3005;
126 | // private static final char SYSINTS = 0x3006;
127 | // private static final char GP_CFG0 = 0x3007;
128 | // private static final char GP_CFG1 = 0x3008;
129 | // private static final char SYSINTE_1 = 0x3009;
130 | // private static final char SYSINTS_1 = 0x300a;
131 | private static final char DEMOD_CTL_1 = 0x300b;
132 | // private static final char IR_SUSPEND = 0x300c;
133 |
134 | // private static final byte DEMODB = 0;
135 | private static final byte USBB = 1;
136 | private static final byte SYSB = 2;
137 | // private static final byte TUNB = 3;
138 | // private static final byte ROMB = 4;
139 | // private static final byte IRB = 5;
140 | private static final byte IICB = 6;
141 |
142 | /*
143 | * Configuration Request Codes
144 | */
145 | // private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
146 | // private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
147 | // private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
148 | // private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
149 | // private static final int SILABSER_SET_BAUDRATE = 0x1E;
150 |
151 | /*
152 | * SILABSER_IFC_ENABLE_REQUEST_CODE
153 | */
154 | // private static final int UART_ENABLE = 0x0001;
155 | // private static final int UART_DISABLE = 0x0000;
156 |
157 | /*
158 | * SILABSER_SET_BAUDDIV_REQUEST_CODE
159 | */
160 | // private static final int BAUD_RATE_GEN_FREQ = 0x384000;
161 |
162 | private static final int E4K_I2C_ADDR = 0xc8;
163 | private static final int E4K_CHECK_ADDR = 0x02;
164 | private static final int E4K_CHECK_VAL = 0x40;
165 |
166 | private static final int FC0013_I2C_ADDR = 0xc6;
167 | private static final int FC0013_CHECK_ADDR = 0x00;
168 | private static final int FC0013_CHECK_VAL = 0xa3;
169 |
170 | private static final int R820T_I2C_ADDR = 0x34;
171 | private static final int R828D_I2C_ADDR = 0x74;
172 | private static final int R820T_CHECK_ADDR = 0x00;
173 | private static final int R820T_CHECK_VAL = 0x69;
174 |
175 | private static final int FC2580_I2C_ADDR = 0xac;
176 | private static final int FC2580_CHECK_ADDR = 0x01;
177 | private static final int FC2580_CHECK_VAL = 0x56;
178 |
179 | private static final int FC0012_I2C_ADDR = 0xc6;
180 | private static final int FC0012_CHECK_ADDR = 0x00;
181 | private static final int FC0012_CHECK_VAL = 0xa1;
182 |
183 | /*
184 | * SILABSER_SET_MHS_REQUEST_CODE
185 | */
186 | // private static final int MCR_DTR = 0x0001;
187 | // private static final int MCR_RTS = 0x0002;
188 | // private static final int MCR_ALL = 0x0003;
189 |
190 | // private static final int CONTROL_WRITE_DTR = 0x0100;
191 | // private static final int CONTROL_WRITE_RTS = 0x0200;
192 |
193 | // private static final int TIMEOUT = 500;
194 | // private static final byte i2c_addr = 0; //FIXME
195 | // private static final long[] null = null;
196 | private static final int RTLSDR_TUNER_UNKNOWN = 0;
197 | private static final int RTLSDR_TUNER_E4000 = 1;
198 | private static final int RTLSDR_TUNER_FC0012 = 2;
199 | private static final int RTLSDR_TUNER_FC0013 = 3;
200 | private static final int RTLSDR_TUNER_FC2580 = 4;
201 | private static final int RTLSDR_TUNER_R820T = 5;
202 | private static final int RTLSDR_TUNER_R828D = 6;
203 | private static final long R820T_IF_FREQ = 3570000;
204 | // private static final String RTLSDR_INACTIVE = null;
205 |
206 | private UsbEndpoint mReadEndpoint;
207 | private boolean tuner = false;
208 | private boolean tuner_exit = false;
209 | private static long rtl_xtal = DEF_RTL_XTAL_FREQ;
210 | private long rate = MAX_SAMP_RATE;
211 | private static long tun_xtal = DEF_RTL_XTAL_FREQ;
212 | // private long freq=DEF_RTL_XTAL_FREQ;
213 | private static int corr = 0;
214 | // private Object e4k_s;
215 | private boolean direct_sampling = false;
216 | private long offs_freq = 0;
217 | private int tuner_type = 0;
218 |
219 | private int ppm_error = 0;
220 | private boolean tuner_set_gain = true;
221 | // private boolean tuner_set_if_gain=false;
222 | // private boolean tuner_set_gain_mode=false;
223 | private boolean tuner_set_bw = true;
224 | private boolean tuner_init = false;
225 | int erro_count = 0;
226 |
227 | // AdsbParse adsb;
228 | public SdrSerialDriverOrig(UsbDevice device, UsbDeviceConnection connection) {
229 | super(device, connection);
230 | }
231 |
232 | private int setConfigSingle(int request, int value) {
233 | return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request,
234 | value, 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
235 | }
236 |
237 | @Override
238 | public void open() throws IOException {
239 | // inteface 0 has 1 bulktransfer read endpoint
240 | boolean opened = false;
241 | try {
242 | for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
243 | UsbInterface usbIface = mDevice.getInterface(i);
244 | if (mConnection.claimInterface(usbIface, true)) {
245 | Log.e(TAG, "claimInterface " + i + " SUCCESS");
246 | } else {
247 | Log.e(TAG, "claimInterface " + i + " FAIL");
248 | }
249 | }
250 | int count = mDevice.getInterfaceCount();
251 | for (int i = 0; i < count; i++) {
252 | UsbInterface intf = mDevice.getInterface(i);
253 | if (intf != null) {
254 | Log.e(TAG,
255 | "intf.getInterfaceClass()=" + i + " "
256 | + intf.getInterfaceClass()
257 | + " intf.getInterfaceSubclass()=" + i + " "
258 | + intf.getInterfaceSubclass()
259 | + " intf.getInterfaceProtocol()=" + i + " "
260 | + intf.getInterfaceProtocol());
261 | Log.e(TAG,
262 | "dataIface.getEndpointCount " + i + " "
263 | + intf.getEndpointCount());
264 | }
265 | int getEndpointCount = intf.getEndpointCount();
266 | for (int j = 0; j < getEndpointCount; j++) {
267 | UsbEndpoint ep = intf.getEndpoint(j);
268 | Log.e(TAG,
269 | "found endpoint getEndpointNumber= "
270 | + ep.getEndpointNumber());
271 | Log.e(TAG, "found endpoint type= " + ep.getType());
272 | Log.e(TAG,
273 | "found endpoint getDirection= " + ep.getDirection());
274 | Log.e(TAG,
275 | "found endpoint getMaxPacketSize= "
276 | + ep.getMaxPacketSize());
277 |
278 | if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
279 | if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
280 | mReadEndpoint = ep;
281 | Log.e(TAG, "found READ USB_ENDPOINT_XFER_BULK");
282 | } else {
283 | Log.e(TAG,
284 | "found WRITE USB_DIR_OUT->USB_ENDPOINT_XFER_BULK");
285 | }
286 | }
287 | }
288 | opened = true;
289 |
290 | }
291 | // if(myTuner == null)
292 | myTuner = rtlsdr_detect();
293 | if (myTuner != null) {
294 |
295 | StartDevice();
296 |
297 | }
298 | } finally {
299 | if (!opened) {
300 | close();
301 | }
302 | }
303 | }
304 |
305 | @Override
306 | public void close() throws IOException {
307 | rtlsdr_deinit_baseband();
308 |
309 | if (myTuner != null)
310 | myTuner.exit(0);
311 | mConnection.close();
312 | }
313 |
314 | @Override
315 | public int read(byte[] dest, int timeoutMillis) throws IOException {
316 | final int totalBytesRead;
317 |
318 | synchronized (mReadBufferLock) {
319 | int readAmt = Math.min(dest.length, mReadBuffer.length);
320 | totalBytesRead = mConnection.bulkTransfer(mReadEndpoint,
321 | mReadBuffer, readAmt, timeoutMillis * 1000);
322 | // if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
323 | // throw new IOException("Expected at least " +
324 | // MODEM_STATUS_HEADER_LENGTH + " bytes");
325 | // }
326 | if (totalBytesRead < 0) {
327 | Log.e(TAG, " mConnection.bulkTransfer ERROR totalBytesRead="
328 | + totalBytesRead);
329 |
330 | } else {
331 | System.arraycopy(mReadBuffer, 0, dest, 0, totalBytesRead);
332 | }
333 | return totalBytesRead;
334 | }
335 |
336 | }
337 |
338 | @Override
339 | public int write(byte[] src, int timeoutMillis) throws IOException {
340 |
341 | Log.e(TAG, "Writes not support yet writeLength= " + src.length);
342 |
343 | return src.length;
344 | }
345 |
346 | private void StartDevice() {
347 | /* Set gain, frequency, sample rate, and reset the device. */
348 |
349 | rtlsdr_set_tuner_gain_mode((gain == MODES_AUTO_GAIN) ? false : true);
350 | if (gain != MODES_AUTO_GAIN) {
351 | if (gain == MODES_MAX_GAIN) {
352 | /* Find the maximum gain available. */
353 | int numgains;
354 | int[] gains = new int[100];
355 |
356 | numgains = rtlsdr_get_tuner_gains(gains);
357 | gain = gains[numgains - 1];
358 | Log.e(TAG,
359 | "Max available gain is: "
360 | + String.format("%.2f", gain / 10.0));
361 | }
362 | rtlsdr_set_tuner_gain(gain);
363 | Log.e(TAG, "Setting gain to: " + String.format("%.2f", gain / 10.0));
364 | } else {
365 | Log.e(TAG, "Using automatic gain control.\n");
366 | }
367 | rtlsdr_set_freq_correction(ppm_error);
368 | if (enable_agc)
369 | rtlsdr_set_agc_mode(true);
370 | rtlsdr_set_center_freq(this.freq);
371 | // rtlsdr_set_tuner_gain_mode(true);//true == AGC
372 | rtlsdr_set_sample_rate(MODES_DEFAULT_RATE);
373 | rtlsdr_reset_buffer();
374 | Log.e(TAG,
375 | "Gain reported by device: "
376 | + String.format("%.2f", rtlsdr_get_tuner_gain() / 10.0));
377 | return;
378 | }
379 |
380 | public static Map getSupportedDevices() {
381 | final Map supportedDevices = new LinkedHashMap();
382 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR), new int[] {
383 | UsbId.SDR_SDR2838, UsbId.SDR_SDR2832 });
384 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_TERRACTEC),
385 | new int[] { UsbId.TER_00A9, UsbId.TER_00B3, UsbId.TER_00B4,
386 | UsbId.TER_00B5, UsbId.TER_00B7, UsbId.TER_00B8,
387 | UsbId.TER_00B9, UsbId.TER_00C0, UsbId.TER_00C6,
388 | UsbId.TER_00D3, UsbId.TER_00D7, UsbId.TER_00E0 });
389 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR2), new int[] {
390 | UsbId.SDR2_SDR169, UsbId.SDR2_SDR179, UsbId.SDR2_SDR180,
391 | UsbId.SDR2_SDR183, UsbId.SDR2_SDR198, UsbId.SDR2_SDR211,
392 | UsbId.SDR2_SDR215, UsbId.SDR2_SDR224 });
393 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR3), new int[] {
394 | UsbId.SDR3_SDR1568, UsbId.SDR3_SDR1616, UsbId.SDR3_SDR1664 });
395 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR4), new int[] {
396 | UsbId.SDR4_SDR47107, UsbId.SDR4_SDR51203, UsbId.SDR4_SDR53894,
397 | UsbId.SDR4_SDR55299 });
398 | supportedDevices
399 | .put(Integer.valueOf(UsbId.VENDOR_SDR5), new int[] {
400 | UsbId.SDR5_SDR54163, UsbId.SDR5_SDR54164,
401 | UsbId.SDR5_SDR54165, UsbId.SDR5_SDR54168,
402 | UsbId.SDR5_SDR54173, UsbId.SDR5_SDR54180 });
403 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR6),
404 | new int[] { UsbId.SDR6_SDR28799 });
405 | supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SDR7), new int[] {
406 | UsbId.SDR7_SDR4353, UsbId.SDR7_SDR4354, UsbId.SDR7_SDR4355 });
407 | return supportedDevices;
408 | }
409 |
410 | private static int libusb_control_transfer(byte requestType, byte request,
411 | char value, char index, byte[] buffer, char length, int timeout) {
412 | return mConnection.controlTransfer(requestType, request, value, index,
413 | buffer, length, timeout);
414 | }
415 |
416 | private static int rtlsdr_read_array(byte iicb2, char addr, byte[] data,
417 | byte len) {
418 | int r;
419 | char index = (char) (iicb2 << 8);
420 |
421 | r = libusb_control_transfer(CTRL_IN, (byte) 0, addr, index, data,
422 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
423 |
424 | if (r < 0) {
425 | Log.e("rtlsdr_read_array", " error" + len);
426 | Log.e("rtlsdr_read_array",
427 | "addr 0x" + Integer.toHexString((int) addr) + " index 0x"
428 | + Integer.toHexString((int) index) + " array "
429 | + data[0] + " len " + len);
430 | }
431 | return r;
432 | }
433 |
434 | private static int rtlsdr_write_array(byte iicb2, char addr, byte[] array,
435 | byte len) {
436 | int r;
437 | char index = (char) ((iicb2 << 8) | 0x10);
438 |
439 | r = libusb_control_transfer(CTRL_OUT, (byte) 0, addr, index, array,
440 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
441 |
442 | if (r < 0) {
443 | Log.e("rtlsdr_write_array",
444 | "addr 0x" + Integer.toHexString((int) addr) + " index 0x"
445 | + Integer.toHexString((int) index) + " array "
446 | + array[0] + " len " + len);
447 | Log.e("rtlsdr_write_array", " error byte count " + len);
448 | }
449 | return r;
450 | }
451 |
452 | public static int rtlsdr_i2c_write_reg(byte i2c_addr, char reg, char val) {
453 | char addr = (char) i2c_addr;
454 | byte[] data = new byte[2];
455 |
456 | data[0] = (byte) reg;
457 | data[1] = (byte) val;
458 | return rtlsdr_write_array(IICB, addr, data, (byte) 2);
459 | }
460 |
461 | public static byte rtlsdr_i2c_read_reg(int e4kI2cAddr, int e4kCheckAddr) {
462 | char addr = (char) e4kI2cAddr;
463 | byte[] data = new byte[2];
464 | byte[] out = new byte[2];
465 | out[0] = (byte) e4kCheckAddr;
466 | rtlsdr_write_array(IICB, addr, out, (byte) 1);
467 | rtlsdr_read_array(IICB, addr, data, (byte) 1);
468 |
469 | return data[0];
470 | }
471 |
472 | public static int rtlsdr_get_tuner_clock() {
473 | long[] tuner_freq = new long[1];
474 | long[] xtal_freq = new long[1];
475 | /* read corrected clock value */
476 | if (rtlsdr_get_xtal_freq(xtal_freq, tuner_freq) < 0)
477 | return 0;
478 |
479 | return (int) tuner_freq[0];
480 | }
481 |
482 | private static int rtlsdr_i2c_write(byte i2c_addr, byte[] buffer, byte len) {
483 | byte addr = i2c_addr;
484 |
485 | return rtlsdr_write_array(IICB, (char) addr, buffer, len);
486 | }
487 |
488 | private static int rtlsdr_i2c_read(byte i2c_addr, byte[] buffer, byte len) {
489 | byte addr = i2c_addr;
490 |
491 | return rtlsdr_read_array(IICB, (char) addr, buffer, (byte) len);
492 | }
493 |
494 | private char rtlsdr_read_reg(byte block, char addr, byte len) {
495 | int r = 0;
496 | byte[] data = new byte[2];
497 | char index = (char) (block << 8);
498 | char reg;
499 |
500 | r = libusb_control_transfer(CTRL_IN, (byte) 0, addr, index, data,
501 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
502 |
503 | if (r < 0)
504 | Log.e(TAG, "rtlsdr_read_reg failed " + r);
505 |
506 | reg = (char) ((data[1] << 8) | data[0]);
507 |
508 | return reg;
509 | }
510 |
511 | private int rtlsdr_write_reg(byte block, char addr, char val, byte len) {
512 | int r = 0;
513 | byte[] data = new byte[2];
514 |
515 | char index = (char) ((block << 8) | 0x10);
516 |
517 | if (len == 1)
518 | data[0] = (byte) (val & 0xff);
519 | else
520 | data[0] = (byte) (val >> 8);
521 |
522 | data[1] = (byte) (val & 0xff);
523 |
524 | r = libusb_control_transfer(CTRL_OUT, (byte) 0, addr, index, data,
525 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
526 |
527 | if (r < 0) {
528 | Log.e("rtlsdr_write_reg", "block " + block + " addr " + " val "
529 | + " len " + len);
530 | Log.e("rtlsdr_write_reg", "Line "
531 | + Thread.currentThread().getStackTrace()[2].getLineNumber());
532 | }
533 | return r;
534 | }
535 |
536 | private char rtlsdr_demod_read_reg(byte page, char addr, byte len) {
537 | int r;
538 | byte[] data = new byte[2];
539 |
540 | char index = (char) page;
541 | char reg;
542 | addr = (char) ((addr << 8) | 0x20);
543 |
544 | r = libusb_control_transfer(CTRL_IN, (byte) 0, addr, index, data,
545 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
546 |
547 | if (r < 0) {
548 | Log.e(TAG, "rtlsdr_demod_read_reg error " + r);
549 | Log.e(TAG,
550 | " addr " + Integer.toHexString((int) addr) + " index "
551 | + Integer.toHexString((int) index) + " data[0] "
552 | + Integer.toHexString((int) data[0]) + " data[1] "
553 | + Integer.toHexString((int) data[1]) + " len "
554 | + Integer.toHexString((int) len));
555 | }
556 | reg = (char) ((data[1] << 8) | data[0]);
557 |
558 | return ((char) r);
559 | }
560 |
561 | private int rtlsdr_demod_write_reg(byte page, char addr, char val, byte len) {
562 | int r;
563 | byte[] data = new byte[2];
564 | char index = (char) (0x10 | page);
565 | addr = (char) ((addr << 8) | 0x20);
566 |
567 | if (len == 1)
568 | data[0] = (byte) (val & 0xff);
569 | else
570 | data[0] = (byte) (val >> 8);
571 |
572 | data[1] = (byte) (val & 0xff);
573 |
574 | r = libusb_control_transfer(CTRL_OUT, (byte) 0, addr, index, data,
575 | (char) len, USB_WRITE_TIMEOUT_MILLIS);
576 |
577 | if (r < 0) {
578 | Log.e(TAG, "rtlsdr_demod_write_reg failed " + r);
579 | Log.e(TAG,
580 | " addr " + Integer.toHexString((int) addr) + " index "
581 | + Integer.toHexString((int) index) + " data[0] "
582 | + Integer.toHexString((int) data[0]) + " data[1] "
583 | + Integer.toHexString((int) data[1]) + " len "
584 | + Integer.toHexString((int) len));
585 | }
586 | rtlsdr_demod_read_reg((byte) 0x0a, (char) 0x01, (byte) 1);
587 |
588 | return (r == len) ? len : -1;
589 | }
590 |
591 | private void rtlsdr_set_gpio_bit(byte gpio, boolean val) {
592 | int r;
593 |
594 | gpio = (byte) (1 << gpio);
595 | r = rtlsdr_read_reg(SYSB, GPO, (byte) 1);
596 | r = (val ? (r | gpio) : (r & ~gpio));
597 | rtlsdr_write_reg(SYSB, GPO, (char) r, (byte) 1);
598 | }
599 |
600 | private void rtlsdr_set_gpio_output(byte gpio) {
601 | int r;
602 | gpio = (byte) (1 << gpio);
603 |
604 | r = rtlsdr_read_reg(SYSB, GPD, (byte) 1);
605 | rtlsdr_write_reg(SYSB, GPO, (char) (r & ~gpio), (byte) 1);
606 | r = rtlsdr_read_reg(SYSB, GPOE, (byte) 1);
607 | rtlsdr_write_reg(SYSB, GPOE, (char) (r | gpio), (byte) 1);
608 | }
609 |
610 | private void rtlsdr_set_i2c_repeater(boolean on) {
611 | rtlsdr_demod_write_reg((byte) 1, (char) 0x01,
612 | (char) (on ? 0x18 : 0x10), (byte) 1);
613 | }
614 |
615 | private void rtlsdr_init_baseband() {
616 | int i = 0;
617 | int ret = 0;
618 | /*
619 | * default FIR coefficients used for DAB/FM by the Windows driver, the
620 | * DVB driver uses different ones
621 | */
622 | char[] fir_coeff = { 0xca, 0xdc, 0xd7, 0xd8, 0xe0, 0xf2, 0x0e, 0x35,
623 | 0x06, 0x50, 0x9c, 0x0d, 0x71, 0x11, 0x14, 0x71, 0x74, 0x19,
624 | 0x41, 0xa5, };
625 |
626 | /* initialize USB */
627 | ret = rtlsdr_write_reg(USBB, USB_SYSCTL, (char) 0x09, (byte) 1);
628 | ret = rtlsdr_write_reg(USBB, USB_EPA_MAXPKT, (char) 0x0002, (byte) 2);
629 | ret = rtlsdr_write_reg(USBB, USB_EPA_CTL, (char) 0x1002, (byte) 2);
630 |
631 | /* poweron demod */
632 | ret = rtlsdr_write_reg(SYSB, DEMOD_CTL_1, (char) 0x22, (byte) 1);
633 | ret = rtlsdr_write_reg(SYSB, DEMOD_CTL, (char) 0xe8, (byte) 1);
634 |
635 | /* reset demod (bit 3, soft_rst) */
636 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x01, (char) 0x14,
637 | (byte) 1);
638 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x01, (char) 0x10,
639 | (byte) 1);
640 |
641 | /* disable spectrum inversion and adjacent channel rejection */
642 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x15, (char) 0x00,
643 | (byte) 1);
644 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x16, (char) 0x0000,
645 | (byte) 2);
646 |
647 | /* clear both DDC shift and IF frequency registers */
648 | for (i = 0; i < 6; i++) {
649 | ret = rtlsdr_demod_write_reg((byte) 1, (char) (0x16 + i),
650 | (char) 0x00, (byte) 1);
651 | }
652 |
653 | /* set FIR coefficients */
654 | for (i = 0; i < fir_coeff.length; i++) {
655 | ret = rtlsdr_demod_write_reg((byte) 1, (char) (0x1c + i),
656 | fir_coeff[i], (byte) 1);
657 | }
658 | /* enable SDR mode, disable DAGC (bit 5) */
659 | ret = rtlsdr_demod_write_reg((byte) 0, (char) 0x19, (char) 0x05,
660 | (byte) 1);
661 |
662 | /* init FSM state-holding register */
663 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x93, (char) 0xf0,
664 | (byte) 1);
665 |
666 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x94, (char) 0x0f,
667 | (byte) 1);
668 |
669 | /* disable AGC (en_dagc, bit 0) (this seems to have no effect) */
670 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x11, (char) 0x00,
671 | (byte) 1);
672 |
673 | /* disable RF and IF AGC loop */
674 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0x04, (char) 0x00,
675 | (byte) 1);
676 |
677 | /* disable PID filter (enable_PID = 0) */
678 | ret = rtlsdr_demod_write_reg((byte) 0, (char) 0x61, (char) 0x60,
679 | (byte) 1);
680 |
681 | /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
682 | ret = rtlsdr_demod_write_reg((byte) 0, (char) 0x06, (char) 0x80,
683 | (byte) 1);
684 |
685 | /*
686 | * Enable Zero-IF mode (en_bbin bit), DC cancellation (en_dc_est), IQ
687 | * estimation/compensation (en_iq_comp, en_iq_est)
688 | */
689 | ret = rtlsdr_demod_write_reg((byte) 1, (char) 0xb1, (char) 0x1b,
690 | (byte) 1);
691 |
692 | /* disable 4.096 MHz clock output on pin TP_CK0 */
693 | ret = rtlsdr_demod_write_reg((byte) 0, (char) 0x0d, (char) 0x83,
694 | (byte) 1);
695 |
696 | }
697 |
698 | private int rtlsdr_deinit_baseband() {
699 | int r = 0;
700 | int ret = 0;
701 |
702 | if ((tuner) && (!this.tuner_exit)) {
703 | rtlsdr_set_i2c_repeater(true);
704 |
705 | rtlsdr_set_i2c_repeater(false);
706 | }
707 |
708 | /* poweroff demodulator and ADCs */
709 | ret = rtlsdr_write_reg(SYSB, DEMOD_CTL, (char) 0x20, (byte) 1);
710 | if (ret != 0)
711 | Log.e(TAG, " ret " + ret + "Line "
712 | + Thread.currentThread().getStackTrace()[2].getLineNumber());
713 | tuner_exit = true;
714 | tuner = false;
715 | return r;
716 | }
717 |
718 | private int rtlsdr_set_if_freq(long freq) {
719 | // long [] rtl_xtal = new long[1] ;
720 | // long [] rtl_dummy = new long[1] ;
721 | long if_freq = 0;
722 | char tmp;
723 | int r;
724 |
725 | /* read corrected clock value */
726 | // if (rtlsdr_get_xtal_freq(rtl_xtal, rtl_dummy) < 0) return -2;
727 |
728 | if_freq = (long) (((freq * TWO_POW(22)) / rtl_xtal) * (-1));
729 | // if(rtl_xtal !=0 ) if_freq = (freq/rtl_xtal) & 0x003fffff;
730 | tmp = (char) ((if_freq >> 16) & 0x3f);
731 | r = rtlsdr_demod_write_reg((byte) 1, (char) 0x19, tmp, (byte) 1);
732 | tmp = (char) ((if_freq >> 8) & 0xff);
733 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x1a, tmp, (byte) 1);
734 | tmp = (char) (if_freq & 0xff);
735 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x1b, tmp, (byte) 1);
736 |
737 | return r;
738 | }
739 |
740 | private double TWO_POW(int i) {
741 | return (1 << (i));
742 |
743 | }
744 |
745 | private int rtlsdr_set_sample_freq_correction(int ppm) {
746 | int r = 0;
747 | char tmp;
748 | char offs = (char) (ppm * (-1) * TWO_POW(24) / 1000000);
749 |
750 | tmp = (char) (offs & 0xff);
751 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x3f, tmp, (byte) 1);
752 | tmp = (char) ((offs >> 8) & 0x3f);
753 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x3e, tmp, (byte) 1);
754 |
755 | return r;
756 | }
757 |
758 | private int rtlsdr_set_xtal_freq(long rtl_freq, long tuner_freq) {
759 | int r = 0;
760 |
761 | if (rtl_freq > 0
762 | && (rtl_freq < MIN_RTL_XTAL_FREQ || rtl_freq > MAX_RTL_XTAL_FREQ))
763 | return -2;
764 |
765 | if (rtl_freq > 0 && rtl_xtal != rtl_freq) {
766 | rtl_xtal = rtl_freq;
767 |
768 | /* update xtal-dependent settings */
769 | if (this.rate != 0)
770 | r = rtlsdr_set_sample_rate(this.rate);
771 | }
772 |
773 | if (tun_xtal != tuner_freq) {
774 | if (0 == tuner_freq)
775 | tun_xtal = rtl_xtal;
776 | else
777 | tun_xtal = tuner_freq;
778 |
779 | /* read corrected clock value into e4k structure */
780 | // if (rtlsdr_get_xtal_freq(null, /*this.e4k_s.vco.fosc
781 | // fixxme*/null) < 0) return -3;
782 |
783 | /* update xtal-dependent settings */
784 | if (this.freq != 0)
785 | r = rtlsdr_set_center_freq(this.freq);
786 | }
787 |
788 | return r;
789 | }
790 |
791 | private static double APPLY_PPM_CORR(long val, int ppm) {
792 | return (((val) * (1.0 + (ppm) / 1e6)));
793 | }
794 |
795 | private static int rtlsdr_get_xtal_freq(long[] rtl_xtal2, long[] tuner_freq) {
796 |
797 | // #define APPLY_PPM_CORR(val,ppm) (((val) * (1.0 + (ppm) / 1e6)))
798 |
799 | rtl_xtal2[0] = (long) APPLY_PPM_CORR(rtl_xtal, corr);
800 |
801 | tuner_freq[0] = (long) APPLY_PPM_CORR(tun_xtal, corr);
802 |
803 | return 0;
804 | }
805 |
806 | private int rtlsdr_write_eeprom(byte[] data, char offset, char len)
807 | throws InterruptedException {
808 | int r = 0;
809 | int i;
810 | byte[] cmd = new byte[2];
811 |
812 | // if (!dev) return -1;
813 |
814 | if ((len + offset) > 256)
815 | return -2;
816 |
817 | for (i = 0; i < len; i++) {
818 | cmd[0] = (byte) (i + offset);
819 | r = rtlsdr_write_array(IICB, EEPROM_ADDR, cmd, (byte) 1);
820 | r = rtlsdr_read_array(IICB, EEPROM_ADDR, cmd, (byte) 1);
821 |
822 | /* only write the byte if it differs */
823 | if (cmd[1] == data[i])
824 | continue;
825 |
826 | cmd[1] = data[i];
827 | r = rtlsdr_write_array(IICB, EEPROM_ADDR, cmd, (byte) 2);
828 | if (r != cmd.length)
829 | return -3;
830 |
831 | /*
832 | * for some EEPROMs (e.g. ATC 240LC02) we need a delay between write
833 | * operations, otherwise they will fail
834 | */
835 |
836 | Thread.sleep(5000);
837 |
838 | // usleep(5000);
839 |
840 | }
841 |
842 | return 0;
843 | }
844 |
845 | private int rtlsdr_read_eeprom(byte[] data, byte[] offset, char len) {
846 | int r = 0;
847 | int i;
848 | byte[] output = new byte[2];
849 |
850 | if ((len + offset[0]) > 256) {
851 | Log.e(TAG, " rtlsdr_read_eeprom offset + len > 256");
852 | return -2;
853 | }
854 |
855 | r = rtlsdr_write_array(IICB, EEPROM_ADDR, offset, (byte) 1);
856 | if (r < 0)
857 | return -3;
858 |
859 | for (i = 0; i < len; i++) {
860 | output[0] = data[i];
861 | r = rtlsdr_read_array(IICB, EEPROM_ADDR, output, (byte) 1);
862 |
863 | if (r < 0) {
864 | Log.e(TAG, " rtlsdr_read_eeprom FAILED");
865 | return -3;
866 | }
867 |
868 | }
869 |
870 | return r;
871 | }
872 |
873 | private int rtlsdr_set_center_freq(long freq) {
874 | int r = -1;
875 |
876 | // if (this.tuner ==0) return -1;
877 |
878 | if (this.direct_sampling) {
879 | r = rtlsdr_set_if_freq(freq);
880 | } else if (myTuner != null) {
881 |
882 | rtlsdr_set_i2c_repeater(true);
883 | try {
884 | r = myTuner.set_freq(0, freq);
885 | } catch (IOException e) {
886 |
887 | e.printStackTrace();
888 |
889 | Log.e(TAG, e.toString());
890 | try {
891 | myTuner.set_freq(0, freq - this.offs_freq);
892 | } catch (IOException e1) {
893 |
894 | e1.printStackTrace();
895 | Log.e(TAG, e.toString());
896 | }
897 | }
898 |
899 | rtlsdr_set_i2c_repeater(false);
900 | }
901 |
902 | if (r <= 0)
903 | this.freq = freq;
904 | else
905 | this.freq = 0;
906 | return r;
907 | }
908 |
909 | private long rtlsdr_get_center_freq() {
910 |
911 | return this.freq;
912 | }
913 |
914 | private int rtlsdr_set_freq_correction(int ppm) {
915 | int r = 0;
916 | long[] xtal_freq = new long[1];
917 | long[] tuner_freq2 = new long[1];
918 |
919 | if (corr == ppm)
920 | return -2;
921 |
922 | corr = ppm;
923 |
924 | r |= rtlsdr_set_sample_freq_correction(ppm);
925 |
926 | /* read corrected clock value into e4k structure */
927 | if (rtlsdr_get_xtal_freq(xtal_freq, tuner_freq2) < 0)
928 | return -3;
929 |
930 | if (this.freq != 0) /* retune to apply new correction value */
931 | r |= rtlsdr_set_center_freq(this.freq);
932 |
933 | return r;
934 | }
935 |
936 | private int rtlsdr_get_freq_correction() {
937 |
938 | return corr;
939 | }
940 |
941 | // int rtlsdr_tuner
942 | private int rtlsdr_get_tuner_type() {
943 | // return RTLSDR_TUNER_UNKNOWN;
944 |
945 | return (this.tuner_type);
946 | }
947 |
948 | private int rtlsdr_get_tuner_gains(int[] dst) {
949 | int len;
950 | /* all gain values are expressed in tenths of a dB */
951 | int[] e4k_gains = { -10, 15, 40, 65, 90, 115, 140, 165, 190, 215, 240,
952 | 290, 340, 420 };
953 | int[] fc0012_gains = { -99, -40, 71, 179, 192 };
954 | int[] fc0013_gains = { -99, -73, -65, -63, -60, -58, -54, 58, 61, 63,
955 | 65, 67, 68, 70, 71, 179, 181, 182, 184, 186, 188, 191, 197 };
956 | int[] fc2580_gains = { 0 /* no gain values */};
957 | int[] r820t_gains = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157, 166,
958 | 197, 207, 229, 254, 280, 297, 328, 338, 364, 372, 386, 402,
959 | 421, 434, 439, 445, 480, 496 };
960 | int[] unknown_gains = { 0 /* no gain values */};
961 |
962 | switch (this.tuner_type) {
963 | case RTLSDR_TUNER_E4000:
964 | len = e4k_gains.length;
965 | System.arraycopy(e4k_gains, 0, dst, 0, e4k_gains.length);
966 | break;
967 | case RTLSDR_TUNER_FC0012:
968 | len = fc0012_gains.length;
969 | System.arraycopy(fc0012_gains, 0, dst, 0, fc0012_gains.length);
970 | break;
971 | case RTLSDR_TUNER_FC0013:
972 | len = fc0013_gains.length;
973 | System.arraycopy(fc0013_gains, 0, dst, 0, fc0013_gains.length);
974 | break;
975 | case RTLSDR_TUNER_FC2580:
976 | len = fc2580_gains.length;
977 | System.arraycopy(fc2580_gains, 0, dst, 0, fc2580_gains.length);
978 | break;
979 | case RTLSDR_TUNER_R820T:
980 | len = r820t_gains.length;
981 | System.arraycopy(r820t_gains, 0, dst, 0, r820t_gains.length);
982 | break;
983 | default:
984 |
985 | len = unknown_gains.length;
986 | System.arraycopy(unknown_gains, 0, dst, 0, unknown_gains.length);
987 | break;
988 | }
989 |
990 | return (len);
991 | }
992 |
993 | private int rtlsdr_set_tuner_gain(int inputGain) {
994 | int r = 0;
995 | if (this.tuner_set_gain) {
996 | rtlsdr_set_i2c_repeater(true);
997 | try {
998 | myTuner.set_gain(0, inputGain);
999 | } catch (IOException e) {
1000 | Log.e(TAG, "set_gain error " + e.toString());
1001 | e.printStackTrace();
1002 | }
1003 | rtlsdr_set_i2c_repeater(false);
1004 | }
1005 | gain = inputGain;
1006 | return r;
1007 | }
1008 |
1009 | private long rtlsdr_get_tuner_gain() {
1010 | return this.gain;
1011 | }
1012 |
1013 | private int rtlsdr_set_tuner_if_gain(int stage, int gain) {
1014 | int r = 0;
1015 | if (myTuner != null)
1016 | return -1;
1017 | if (myTuner != null) {
1018 | rtlsdr_set_i2c_repeater(true);
1019 | try {
1020 | myTuner.set_if_gain(0, stage, gain);
1021 | } catch (IOException e) {
1022 | Log.e(TAG, e.toString());
1023 | e.printStackTrace();
1024 | }
1025 | rtlsdr_set_i2c_repeater(false);
1026 | }
1027 |
1028 | return r;
1029 | }
1030 |
1031 | private int rtlsdr_set_tuner_gain_mode(boolean mode) {
1032 | int r = 0;
1033 | // if(myTuner == null) return -1;
1034 |
1035 | if (this.set_gain_mode) {
1036 | rtlsdr_set_i2c_repeater(true);
1037 | try {
1038 | myTuner.set_gain_mode(0, mode);
1039 | } catch (IOException e) {
1040 | Log.e(TAG, e.toString());
1041 | e.printStackTrace();
1042 | }
1043 | rtlsdr_set_i2c_repeater(false);
1044 | }
1045 |
1046 | return r;
1047 | }
1048 |
1049 | private int rtlsdr_set_sample_rate(long samp_rate) {
1050 | int r = 0;
1051 | char tmp;
1052 | long rsamp_ratio;
1053 | double real_rate;
1054 |
1055 | // if (!dev) return -1;
1056 |
1057 | /* check for the maximum rate the resampler supports */
1058 | if (samp_rate > MAX_SAMP_RATE)
1059 | samp_rate = MAX_SAMP_RATE;
1060 |
1061 | rsamp_ratio = (long) ((rtl_xtal * TWO_POW(22)) / samp_rate);
1062 | rsamp_ratio &= ~3;
1063 |
1064 | real_rate = (rtl_xtal * TWO_POW(22)) / rsamp_ratio;
1065 |
1066 | if (samp_rate != real_rate)
1067 | Log.e(TAG, "Exact sample rate is: " + real_rate + " Hz");
1068 |
1069 | if ((myTuner != null) && this.tuner_set_bw) {
1070 | rtlsdr_set_i2c_repeater(true);
1071 | try {
1072 | myTuner.set_bw(0, (int) real_rate);
1073 | } catch (IOException e1) {
1074 | Log.e(TAG, e1.toString());
1075 | e1.printStackTrace();
1076 | }
1077 | if (myTuner != null)
1078 | try {
1079 | myTuner.set_bw(0, (int) real_rate);
1080 | } catch (IOException e) {
1081 | Log.e(TAG, "error set_bw " + real_rate);
1082 | e.printStackTrace();
1083 | }
1084 | rtlsdr_set_i2c_repeater(false);
1085 | }
1086 |
1087 | this.rate = (long) real_rate;
1088 |
1089 | tmp = (char) ((char) (rsamp_ratio >> 16) & 0x0000ffff);
1090 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x9f, tmp, (byte) 2);
1091 | tmp = (char) (rsamp_ratio & 0x0ffff);
1092 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0xa1, tmp, (byte) 2);
1093 |
1094 | r |= rtlsdr_set_sample_freq_correction(corr);
1095 |
1096 | /* reset demod (bit 3, soft_rst) */
1097 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x01, (char) 0x14,
1098 | (byte) 1);
1099 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x01, (char) 0x10,
1100 | (byte) 1);
1101 |
1102 | /* recalculate offset frequency if offset tuning is enabled */
1103 | if (this.offs_freq != 0)
1104 | rtlsdr_set_offset_tuning(true);
1105 |
1106 | return r;
1107 | }
1108 |
1109 | private long rtlsdr_get_sample_rate() {
1110 |
1111 | return this.rate;
1112 | }
1113 |
1114 | private int rtlsdr_set_testmode(boolean on) {
1115 |
1116 | return rtlsdr_demod_write_reg((byte) 0, (char) 0x19, (char) (on ? 0x03
1117 | : 0x05), (byte) 1);
1118 | }
1119 |
1120 | private int rtlsdr_set_agc_mode(boolean on) {
1121 |
1122 | return rtlsdr_demod_write_reg((byte) 0, (char) 0x19, (char) (on ? 0x25
1123 | : 0x05), (byte) 1);
1124 | }
1125 |
1126 | private int rtlsdr_set_direct_sampling(boolean on) {
1127 | int r = 0;
1128 |
1129 | // if (!dev) return -1;
1130 |
1131 | if (on) {
1132 | if ((this.tuner) && this.tuner_exit) {
1133 | rtlsdr_set_i2c_repeater(true);
1134 | // r = this.tuner->exit();
1135 | if (myTuner != null)
1136 | try {
1137 | myTuner.exit(0);
1138 | } catch (IOException e) {
1139 | Log.e(TAG, "myTuner.exit(0) FAILED " + e.toString());
1140 | e.printStackTrace();
1141 | }
1142 | rtlsdr_set_i2c_repeater(false);
1143 | }
1144 |
1145 | /* disable Zero-IF mode */
1146 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0xb1, (char) 0x1a,
1147 | (byte) 1);
1148 |
1149 | /* disable spectrum inversion */
1150 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x15, (char) 0x00,
1151 | (byte) 1);
1152 |
1153 | /* only enable In-phase ADC input */
1154 | r |= rtlsdr_demod_write_reg((byte) 0, (char) 0x08, (char) 0x4d,
1155 | (byte) 1);
1156 |
1157 | /* swap I and Q ADC, this allows to select between two inputs */
1158 | r |= rtlsdr_demod_write_reg((byte) 0, (char) 0x06,
1159 | (char) (on ? 0x90 : 0x80), (byte) 1);
1160 |
1161 | Log.e(TAG,
1162 | "rtlsdr_set_direct_sampling Enabled direct sampling mode, input "
1163 | + on);
1164 | this.direct_sampling = on;
1165 | } else {
1166 | if ((this.myTuner != null) && this.tuner_init) {
1167 | rtlsdr_set_i2c_repeater(true);
1168 | try {
1169 | r |= myTuner.init(0);
1170 | } catch (IOException e) {
1171 |
1172 | e.printStackTrace();
1173 | Log.e(TAG, e.toString());
1174 | }
1175 | rtlsdr_set_i2c_repeater(true);
1176 | }
1177 |
1178 | if (this.tuner_type == RTLSDR_TUNER_R820T) {
1179 | r |= rtlsdr_set_if_freq(R820T_IF_FREQ);
1180 |
1181 | /* enable spectrum inversion */
1182 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0x15, (char) 0x01,
1183 | (byte) 1);
1184 | } else {
1185 | r |= rtlsdr_set_if_freq(0);
1186 |
1187 | /* enable In-phase + Quadrature ADC input */
1188 | r |= rtlsdr_demod_write_reg((byte) 0, (char) 0x08, (char) 0xcd,
1189 | (byte) 1);
1190 |
1191 | /* Enable Zero-IF mode */
1192 | r |= rtlsdr_demod_write_reg((byte) 1, (char) 0xb1, (char) 0x1b,
1193 | (byte) 1);
1194 | }
1195 |
1196 | /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
1197 | r |= rtlsdr_demod_write_reg((byte) 0, (char) 0x06, (char) 0x80,
1198 | (byte) 1);
1199 |
1200 | Log.e(TAG, "Disabled direct sampling mode\n");
1201 | this.direct_sampling = false;
1202 | }
1203 |
1204 | r |= rtlsdr_set_center_freq(this.freq);
1205 |
1206 | return r;
1207 | }
1208 |
1209 | private boolean rtlsdr_get_direct_sampling() {
1210 | return this.direct_sampling;
1211 | }
1212 |
1213 | private int rtlsdr_set_offset_tuning(boolean on) {
1214 | int r = 0;
1215 |
1216 | if (this.tuner_type == RTLSDR_TUNER_R820T)
1217 | return -2;
1218 |
1219 | if (this.direct_sampling)
1220 | return -3;
1221 |
1222 | /* based on keenerds 1/f noise measurements */
1223 | this.offs_freq = on ? ((this.rate / 2) * 170 / 100) : 0;
1224 | // r |= rtlsdr_set_if_freq(this.offs_freq);
1225 |
1226 | if ((this.tuner) && /* this.tuner.set_bw */true) {
1227 | rtlsdr_set_i2c_repeater(true);
1228 | // this.tuner.set_bw(on ? (2 * this.offs_freq) : this. rate);
1229 | rtlsdr_set_i2c_repeater(false);
1230 | }
1231 |
1232 | if (this.freq > this.offs_freq)
1233 | r |= rtlsdr_set_center_freq(this.freq);
1234 |
1235 | return r;
1236 | }
1237 |
1238 | private int rtlsdr_get_offset_tuning() {
1239 | return (this.offs_freq < 0) ? 1 : 0;
1240 | }
1241 |
1242 | private IRtlSdrTuner rtlsdr_detect() throws IOException {
1243 | int reg = 0;
1244 | int ret = 0;
1245 |
1246 | if (myTuner != null) {
1247 | Log.e(TAG, "Error Already called rtlsdr_open()");
1248 | // return (myTuner);
1249 | }
1250 |
1251 | Log.e(TAG, "rtlsdr_open()");
1252 |
1253 | /* perform a dummy write, if it fails, reset the device */
1254 | if ((ret = rtlsdr_write_reg(USBB, USB_SYSCTL, (char) 0x09, (byte) 1)) < 0) {
1255 | if (ret != 0)
1256 | Log.e(TAG,
1257 | "ERROR ret "
1258 | + ret
1259 | + " Line "
1260 | + Thread.currentThread().getStackTrace()[2]
1261 | .getLineNumber());
1262 | Log.e(TAG, "Resetting device...");
1263 |
1264 | }
1265 |
1266 | rtlsdr_init_baseband();
1267 | /* Probe tuners */
1268 | rtlsdr_set_i2c_repeater(true);
1269 |
1270 | reg = rtlsdr_i2c_read_reg(R820T_I2C_ADDR, R820T_CHECK_ADDR) & 0x0000FF;
1271 | if (reg == R820T_CHECK_VAL) {
1272 | Log.e(TAG, "Found Rafael Micro R820T tuner\n");
1273 | this.tuner_type = RTLSDR_TUNER_R820T;
1274 |
1275 | /* disable Zero-IF mode */
1276 | rtlsdr_demod_write_reg((byte) 1, (char) 0xb1, (char) 0x1a, (byte) 1);
1277 |
1278 | /* only enable In-phase ADC input */
1279 | rtlsdr_demod_write_reg((byte) 0, (char) 0x08, (char) 0x4d, (byte) 1);
1280 |
1281 | /*
1282 | * the R820T uses 3.57 MHz IF for the DVB-T 6 MHz mode, and 4.57 MHz
1283 | * for the 8 MHz mode
1284 | */
1285 | rtlsdr_set_if_freq(R820T_IF_FREQ);
1286 |
1287 | /* enable spectrum inversion */
1288 | rtlsdr_demod_write_reg((byte) 1, (char) 0x15, (char) 0x01, (byte) 1);
1289 |
1290 | myTuner = new R820T();
1291 | if (myTuner != null)
1292 | Log.e(TAG, "Error on tuner init");
1293 | myTuner.init(0);
1294 |
1295 | rtlsdr_set_i2c_repeater(false);
1296 |
1297 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1298 |
1299 | return myTuner;
1300 | }
1301 |
1302 | reg = rtlsdr_i2c_read_reg(R828D_I2C_ADDR, R820T_CHECK_ADDR);
1303 | if (reg == R820T_CHECK_VAL) {
1304 | Log.e(TAG, "Found Rafael Micro R828D tuner\n");
1305 | this.tuner_type = RTLSDR_TUNER_R828D;
1306 | myTuner = new R820T();// ??
1307 |
1308 | myTuner.init(0);
1309 | rtlsdr_set_i2c_repeater(false);
1310 | }
1311 |
1312 | /* initialise GPIOs */
1313 | reg = rtlsdr_i2c_read_reg(E4K_I2C_ADDR, E4K_CHECK_ADDR) & 0x000000FF;
1314 | if (reg == E4K_CHECK_VAL) {
1315 | Log.e(TAG, "Found Elonics E4000 tuner");
1316 | this.tuner_type = RTLSDR_TUNER_E4000;
1317 | myTuner = new E4K();
1318 |
1319 | myTuner.init(0);
1320 |
1321 | rtlsdr_set_i2c_repeater(false);
1322 |
1323 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1324 |
1325 | return myTuner;
1326 | }
1327 |
1328 | reg = rtlsdr_i2c_read_reg(FC0013_I2C_ADDR, FC0013_CHECK_ADDR) & 0x000000FF;
1329 | if (reg == FC0013_CHECK_VAL) {
1330 | Log.e(TAG, "Found Fitipower FC0013 tuner");
1331 |
1332 | this.tuner_type = RTLSDR_TUNER_FC0013;
1333 |
1334 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1335 |
1336 | myTuner = new FC0013();
1337 |
1338 | myTuner.init(0);
1339 |
1340 | rtlsdr_set_i2c_repeater(false);
1341 |
1342 | return myTuner;
1343 | }
1344 |
1345 | rtlsdr_set_gpio_output((byte) 5);
1346 |
1347 | /* reset tuner before probing */
1348 | rtlsdr_tuner_reset();
1349 |
1350 | reg = rtlsdr_i2c_read_reg(FC2580_I2C_ADDR, FC2580_CHECK_ADDR) & 0x000000FF;
1351 | if ((reg & 0x7f) == FC2580_CHECK_VAL) {
1352 | Log.e(TAG, "Found FCI 2580 tuner");
1353 | this.tuner_type = RTLSDR_TUNER_FC2580;
1354 | myTuner = new FC2580();
1355 |
1356 | myTuner.init(0);
1357 |
1358 | rtlsdr_set_i2c_repeater(false);
1359 |
1360 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1361 |
1362 | return myTuner;
1363 | }
1364 |
1365 | reg = rtlsdr_i2c_read_reg(FC0012_I2C_ADDR, FC0012_CHECK_ADDR) & 0x000000FF;
1366 | if (reg == FC0012_CHECK_VAL) {
1367 | Log.e(TAG, "Found Fitipower FC0012 tuner");
1368 | rtlsdr_set_gpio_output((byte) 6);
1369 | this.tuner_type = RTLSDR_TUNER_FC0012;
1370 |
1371 | myTuner = new FC0012();
1372 |
1373 | myTuner.init(0);
1374 |
1375 | rtlsdr_set_i2c_repeater(false);
1376 |
1377 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1378 |
1379 | return myTuner;
1380 | }
1381 |
1382 | if (this.tuner_type == RTLSDR_TUNER_UNKNOWN) {
1383 | Log.e(TAG, "No supported tuner found\n");
1384 | rtlsdr_set_direct_sampling(true);
1385 | return null;
1386 | }
1387 |
1388 | tun_xtal = rtl_xtal; /* use the rtl clock value by default */
1389 |
1390 | rtlsdr_set_i2c_repeater(false);
1391 |
1392 | return myTuner;
1393 | }
1394 |
1395 | private void rtlsdr_tuner_led_on() {
1396 | /* reset tuner before probing */
1397 | rtlsdr_set_gpio_bit((byte) 0, true);
1398 | // rtlsdr_set_gpio_bit((byte) 1, false);
1399 | }
1400 |
1401 | private void rtlsdr_tuner_reset() {
1402 | /* reset tuner before probing */
1403 | rtlsdr_set_gpio_bit((byte) 5, true);
1404 | rtlsdr_set_gpio_bit((byte) 5, false);
1405 | }
1406 |
1407 | private int rtlsdr_reset_buffer() {
1408 |
1409 | rtlsdr_write_reg(USBB, USB_EPA_CTL, (char) 0x1002, (byte) 2);
1410 | rtlsdr_write_reg(USBB, USB_EPA_CTL, (char) 0x0000, (byte) 2);
1411 |
1412 | return 0;
1413 | }
1414 |
1415 | private int rtlsdr_read_sync(byte[] buf, int len, int n_read)
1416 | throws IOException {
1417 | return (read(buf, BULK_TIMEOUT));
1418 | // return libusb_bulk_transfer(0x81, buf, len, n_read, BULK_TIMEOUT);
1419 | }
1420 |
1421 | /*
1422 | * @Override public int setBaudRate(int baudRate) throws IOException { //
1423 | * TODO Auto-generated method stub return 0; }
1424 | */
1425 |
1426 | @Override
1427 | public void settings(boolean agc, int mygain, int ppm) {
1428 | enable_agc = agc;
1429 | ppm_error = ppm;
1430 | gain = mygain;
1431 | }
1432 |
1433 | @Override
1434 | public void setParameters(int baudRate, int dataBits, int stopBits,
1435 | int parity) throws IOException {
1436 |
1437 | }
1438 |
1439 | @Override
1440 | public boolean getCD() throws IOException {
1441 | return false;
1442 | }
1443 |
1444 | @Override
1445 | public boolean getCTS() throws IOException {
1446 | return false;
1447 | }
1448 |
1449 | @Override
1450 | public boolean getDSR() throws IOException {
1451 | return false;
1452 | }
1453 |
1454 | @Override
1455 | public boolean getDTR() throws IOException {
1456 | return false;
1457 | }
1458 |
1459 | @Override
1460 | public void setDTR(boolean value) throws IOException {
1461 | }
1462 |
1463 | @Override
1464 | public boolean getRI() throws IOException {
1465 | return false;
1466 | }
1467 |
1468 | @Override
1469 | public boolean getRTS() throws IOException {
1470 | return false;
1471 | }
1472 |
1473 | @Override
1474 | public void setRTS(boolean value) throws IOException {
1475 | }
1476 |
1477 | public static int rtlsdr_i2c_write_fn(byte addr, byte[] buf, byte len) {
1478 | return rtlsdr_i2c_write(addr, buf, len);
1479 |
1480 | }
1481 |
1482 | public static int rtlsdr_i2c_read_fn(byte addr, byte[] buf, byte len) {
1483 | return rtlsdr_i2c_read(addr, buf, len);
1484 |
1485 | }
1486 |
1487 | }
1488 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/SdrUsbId.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android;
2 |
3 | public class SdrUsbId {
4 |
5 | public static final int VENDOR_KYE = 0x0458;
6 | public static final int KYE_RTL2832_707F = 0x707f;
7 |
8 | public static final int VENDOR_RTL = 0x0bda;
9 | public static final int RTL_RTL2832 = 0x2832;
10 | public static final int RTL_RTL2838 = 0x2838;
11 |
12 | public static final int VENDOR_TERRATEC = 0x0ccd;
13 | public static final int TERRATEC_RTL2838_A9 = 0x00a9;
14 | public static final int TERRATEC_RTL2838_B3 = 0x00b3;
15 | public static final int TERRATEC_RTL2838_B4 = 0x00b4;
16 | public static final int TERRATEC_RTL2838_B7 = 0x00b7;
17 | public static final int TERRATEC_RTL2838_C6 = 0x00c6;
18 | public static final int TERRATEC_RTL2838_D3 = 0x00d3;
19 | public static final int TERRATEC_RTL2838_D7 = 0x00d7;
20 | public static final int TERRATEC_RTL2838_E0 = 0x00e0;
21 |
22 | public static final int VENDOR_COMPRO = 0x185b;
23 | public static final int COMPRO_620 = 0x0620;;
24 | public static final int COMPRO_650 = 0x0650;
25 | public static final int COMPRO_680 = 0x0680;
26 |
27 | public static final int VENDOR_AFATECH = 0x01b80;
28 | public static final int AFATECH_RTL2838_D393 = 0xd393;
29 | public static final int AFATECH_RTL2838_D394 = 0xd394;
30 | public static final int AFATECH_RTL2838_D395 = 0xd395;
31 | public static final int AFATECH_RTL2838_D396 = 0xd396;
32 | public static final int AFATECH_RTL2838_D397 = 0xd397;
33 | public static final int AFATECH_RTL2838_D398 = 0xd398;
34 | public static final int AFATECH_RTL2838_D39D = 0xd39d;
35 | public static final int AFATECH_RTL2838_D3A4 = 0xd3a4;
36 |
37 | public static final int VENDOR_DEXATEC = 0x01d19;
38 | public static final int DEXATEC_1101 = 0x1101;
39 | public static final int DEXATEC_1102 = 0x1102;
40 | public static final int DEXATEC_1103 = 0x1103;
41 |
42 | public static final int VENDOR_GTEK = 0x1f4d;
43 | public static final int GTEK_RTL2838_B803 = 0xb803;
44 | public static final int GTEK_RTL2838_C803 = 0xC803;
45 | public static final int GTEK_RTL2838_D286 = 0xd286;
46 | public static final int GTEK_RTL2838_D803 = 0xD803;
47 |
48 | private SdrUsbId() {
49 | throw new IllegalAccessError("Non-instantiable class.");
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/tuners/E4K.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android.tuners;
2 |
3 | import java.io.IOException;
4 |
5 | import com.rtlsdr.android.SdrSerialDriver;
6 |
7 | public class E4K implements IRtlSdrTuner {
8 | class e4k_if_filter {
9 | int E4K_IF_FILTER_MIX;
10 | int E4K_IF_FILTER_CHAN;
11 | int E4K_IF_FILTER_RC;
12 | };
13 |
14 | class e4k_pll_params {
15 | int fosc;
16 | int intended_flo;
17 | int flo;
18 | char x;
19 | byte z;
20 | byte r;
21 | byte r_idx;
22 | byte threephase;
23 | };
24 |
25 | class e4k_band {
26 | int E4K_BAND_VHF2 = 0;
27 | int E4K_BAND_VHF3 = 1;
28 | int E4K_BAND_UHF = 2;
29 | int E4K_BAND_L = 3;
30 | };
31 |
32 | class e4k_state {
33 |
34 | byte i2c_addr;
35 | e4k_band band;
36 | e4k_pll_params vco;
37 |
38 | };
39 |
40 | class reg_field {
41 | byte reg;
42 | byte shift;
43 | byte width;
44 | };
45 |
46 | private final int E4K_I2C_ADDR = 0xC8;
47 | private final int E4K_REG_MASTER1 = 0x00,
48 | E4K_REG_MASTER2 = 0x01,
49 | E4K_REG_MASTER3 = 0x02,
50 | E4K_REG_MASTER4 = 0x03,
51 | E4K_REG_MASTER5 = 0x04,
52 | E4K_REG_CLK_INP = 0x05,
53 | E4K_REG_REF_CLK = 0x06,
54 | E4K_REG_SYNTH1 = 0x07,
55 | E4K_REG_SYNTH2 = 0x08,
56 | E4K_REG_SYNTH3 = 0x09,
57 | E4K_REG_SYNTH4 = 0x0a,
58 | E4K_REG_SYNTH5 = 0x0b,
59 | E4K_REG_SYNTH6 = 0x0c,
60 | E4K_REG_SYNTH7 = 0x0d,
61 | E4K_REG_SYNTH8 = 0x0e,
62 | E4K_REG_SYNTH9 = 0x0f,
63 | E4K_REG_FILT1 = 0x10,
64 | E4K_REG_FILT2 = 0x11,
65 | E4K_REG_FILT3 = 0x12,
66 | // gap
67 | E4K_REG_GAIN1 = 0x14,
68 | E4K_REG_GAIN2 = 0x15,
69 | E4K_REG_GAIN3 = 0x16,
70 | E4K_REG_GAIN4 = 0x17,
71 | // gap
72 | E4K_REG_AGC1 = 0x1a,
73 | E4K_REG_AGC2 = 0x1b,
74 | E4K_REG_AGC3 = 0x1c,
75 | E4K_REG_AGC4 = 0x1d,
76 | E4K_REG_AGC5 = 0x1e,
77 | E4K_REG_AGC6 = 0x1f,
78 | E4K_REG_AGC7 = 0x20,
79 | E4K_REG_AGC8 = 0x21,
80 | // gap
81 | E4K_REG_AGC11 = 0x24,
82 | E4K_REG_AGC12 = 0x25,
83 | // gap
84 | E4K_REG_DC1 = 0x29,
85 | E4K_REG_DC2 = 0x2a,
86 | E4K_REG_DC3 = 0x2b,
87 | E4K_REG_DC4 = 0x2c,
88 | E4K_REG_DC5 = 0x2d,
89 | E4K_REG_DC6 = 0x2e,
90 | E4K_REG_DC7 = 0x2f,
91 | E4K_REG_DC8 = 0x30,
92 | // gap
93 | E4K_REG_QLUT0 = 0x50,
94 | E4K_REG_QLUT1 = 0x51,
95 | E4K_REG_QLUT2 = 0x52,
96 | E4K_REG_QLUT3 = 0x53,
97 | // gap
98 | E4K_REG_ILUT0 = 0x60,
99 | E4K_REG_ILUT1 = 0x61,
100 | E4K_REG_ILUT2 = 0x62,
101 | E4K_REG_ILUT3 = 0x63,
102 | // gap
103 | E4K_REG_DCTIME1 = 0x70, E4K_REG_DCTIME2 = 0x71,
104 | E4K_REG_DCTIME3 = 0x72, E4K_REG_DCTIME4 = 0x73,
105 | E4K_REG_PWM1 = 0x74, E4K_REG_PWM2 = 0x75, E4K_REG_PWM3 = 0x76,
106 | E4K_REG_PWM4 = 0x77, E4K_REG_BIAS = 0x78,
107 | E4K_REG_CLKOUT_PWDN = 0x7a, E4K_REG_CHFILT_CALIB = 0x7b,
108 | E4K_REG_I2C_REG_ADDR = 0x7d, E4K_AGC_MOD_SERIAL = 0x0,
109 | E4K_AGC_MOD_IF_PWM_LNA_SERIAL = 0x1,
110 | E4K_AGC_MOD_IF_PWM_LNA_AUTONL = 0x2,
111 | E4K_AGC_MOD_IF_PWM_LNA_SUPERV = 0x3,
112 | E4K_AGC_MOD_IF_SERIAL_LNA_PWM = 0x4,
113 | E4K_AGC_MOD_IF_PWM_LNA_PWM = 0x5,
114 | E4K_AGC_MOD_IF_DIG_LNA_SERIAL = 0x6,
115 | E4K_AGC_MOD_IF_DIG_LNA_AUTON = 0x7,
116 | E4K_AGC_MOD_IF_DIG_LNA_SUPERV = 0x8,
117 | E4K_AGC_MOD_IF_SERIAL_LNA_AUTON = 0x9,
118 | E4K_AGC_MOD_IF_SERIAL_LNA_SUPERV = 0xa, E4K_BAND_VHF2 = 0,
119 | E4K_BAND_VHF3 = 1, E4K_BAND_UHF = 2, E4K_BAND_L = 3,
120 | E4K_F_MIX_BW_27M = 0, E4K_F_MIX_BW_4M6 = 8, E4K_F_MIX_BW_4M2 = 9,
121 | E4K_F_MIX_BW_3M8 = 10, E4K_F_MIX_BW_3M4 = 11, E4K_F_MIX_BW_3M = 12,
122 | E4K_F_MIX_BW_2M7 = 13, E4K_F_MIX_BW_2M3 = 14,
123 | E4K_F_MIX_BW_1M9 = 15, E4K_IF_FILTER_MIX = 0,
124 | E4K_IF_FILTER_CHAN = 1, E4K_IF_FILTER_RC = 3;
125 |
126 | private final int E4K_MASTER1_RESET = (1 << 0);
127 | private final int E4K_MASTER1_NORM_STBY = (1 << 1);
128 | private final int E4K_MASTER1_POR_DET = (1 << 2);
129 | private final int E4K_SYNTH1_PLL_LOCK = (1 << 0);
130 | private final int E4K_SYNTH1_BAND_SHIF = 1;
131 | private final int E4K_SYNTH7_3PHASE_EN = (1 << 3);
132 | private final int E4K_SYNTH8_VCOCAL_UPD = (1 << 2);
133 | private final int E4K_FILT3_DISABLE = (1 << 5);
134 | private final int E4K_AGC1_LIN_MODE = (1 << 4);
135 | private final int E4K_AGC1_LNA_UPDATE = (1 << 5);
136 | private final int E4K_AGC1_LNA_G_LOW = (1 << 6);
137 | private final int E4K_AGC1_LNA_G_HIGH = (1 << 7);
138 | private final int E4K_AGC6_LNA_CAL_REQ = (1 << 4);
139 | private final int E4K_AGC7_MIX_GAIN_AUTO = (1 << 0);
140 | private final int E4K_AGC7_GAIN_STEP_5dB = (1 << 5);
141 | private final int E4K_AGC8_SENS_LIN_AUTO = (1 << 0);
142 | private final int E4K_AGC11_LNA_GAIN_ENH = (1 << 0);
143 | private final int E4K_DC1_CAL_REQ = (1 << 0);
144 | private final int E4K_DC5_I_LUT_EN = (1 << 0);
145 | private final int E4K_DC5_Q_LUT_EN = (1 << 1);
146 | private final int E4K_DC5_RANGE_DET_EN = (1 << 2);
147 | private final int E4K_DC5_RANGE_EN = (1 << 3);
148 | private final int E4K_DC5_TIMEVAR_EN = (1 << 4);
149 | private final int E4K_CLKOUT_DISABLE = 0x96;
150 | private final int E4K_CHFCALIB_CMD = (1 << 0);
151 | private final int E4K_AGC1_MOD_MASK = 0xF;
152 |
153 | private final byte[] if_stage1_gain = { -3, 6 };
154 |
155 | private final byte[] if_stage23_gain = { 0, 3, 6, 9 };
156 |
157 | private final byte[] if_stage4_gain = { 0, 1, 2, 2 };
158 |
159 | private final byte[] if_stage56_gain = { 3, 6, 9, 12, 15, 15, 15, 15 };
160 |
161 | private final byte[] if_stage_gain[] = { null, if_stage1_gain,
162 | if_stage23_gain, if_stage23_gain, if_stage4_gain, if_stage56_gain,
163 | if_stage56_gain };
164 |
165 | private final int[] if_stage_gain_len = { 0, if_stage1_gain.length,
166 | if_stage23_gain.length, if_stage23_gain.length,
167 | if_stage4_gain.length, if_stage56_gain.length,
168 | if_stage56_gain.length };
169 |
170 | @Override
171 | public int init(int param) throws IOException {
172 | // TODO Auto-generated method stub
173 |
174 | return e4k_init();
175 | }
176 |
177 | @Override
178 | public int exit(int param) throws IOException {
179 | // TODO Auto-generated method stub
180 | return 0;
181 | }
182 |
183 | @Override
184 | public int set_freq(int param, long freq) throws IOException {
185 | // TODO Auto-generated method stub
186 | return 0;
187 | }
188 |
189 | @Override
190 | public int set_bw(int param, int bw) throws IOException {
191 | // TODO Auto-generated method stub
192 | return 0;
193 | }
194 |
195 | @Override
196 | public int set_gain(int param, int gain) throws IOException {
197 | // TODO Auto-generated method stub
198 | return 0;
199 | }
200 |
201 | @Override
202 | public int set_if_gain(int param, int stage, int gain) throws IOException {
203 | // TODO Auto-generated method stub
204 | return 0;
205 | }
206 |
207 | @Override
208 | public int set_gain_mode(int param, boolean manual) throws IOException {
209 | // TODO Auto-generated method stub
210 | return 0;
211 | }
212 |
213 | private int MHZ(int x) {
214 | return ((x) * 1000 * 1000);
215 | }
216 |
217 | private int KHZ(int x) {
218 | return ((x) * 1000);
219 | }
220 |
221 | byte e4k_reg_read(int reg) {
222 | return SdrSerialDriver.rtlsdr_i2c_read_reg((char) E4K_I2C_ADDR, reg);
223 | }
224 |
225 | int e4k_reg_write(int reg, int val) {
226 | return SdrSerialDriver.rtlsdr_i2c_write_reg((byte) E4K_I2C_ADDR,
227 | (char) reg, (char) val);
228 | }
229 |
230 | /*
231 | * ! \brief Set or clear some (masked) bits inside a register \param[in] e4k
232 | * reference to the tuner \param[in] reg number of the register \param[in]
233 | * mask bit-mask of the value \param[in] val data value to be written to
234 | * register \returns 0 on success, negative in case of error
235 | */
236 | int e4k_reg_set_mask(byte reg, char mask, char val) {
237 | byte tmp = e4k_reg_read(reg);
238 |
239 | if ((tmp & mask) == val)
240 | return 0;
241 |
242 | return e4k_reg_write(reg, (tmp & ~mask) | (val & mask));
243 | }
244 |
245 | /*
246 | * ! \brief Enables / Disables the channel filter \param[in] e4k reference
247 | * to the tuner chip \param[in] on 1=filter enabled, 0=filter disabled
248 | * \returns 0 success, negative errors
249 | */
250 | int e4k_if_filter_chan_enable(boolean on) {
251 | return e4k_reg_set_mask((byte) E4K_REG_FILT3, (char) E4K_FILT3_DISABLE,
252 | (char) (on ? 0 : E4K_FILT3_DISABLE));
253 | }
254 |
255 | /*
256 | * ! \brief Initialize the E4K tuner
257 | */
258 | int e4k_init() {
259 | /* make a dummy i2c read or write command, will not be ACKed! */
260 | e4k_reg_read((byte) 0);
261 |
262 | /* Make sure we reset everything and clear POR indicator */
263 | e4k_reg_write((byte) E4K_REG_MASTER1, (byte) (E4K_MASTER1_RESET
264 | | E4K_MASTER1_NORM_STBY | E4K_MASTER1_POR_DET));
265 |
266 | /* Configure clock input */
267 | e4k_reg_write((byte) E4K_REG_CLK_INP, (byte) 0x00);
268 |
269 | /* Disable clock output */
270 | e4k_reg_write((byte) E4K_REG_REF_CLK, (byte) 0x00);
271 | e4k_reg_write((byte) E4K_REG_CLKOUT_PWDN, (byte) 0x96);
272 |
273 | /* Write some magic values into registers */
274 | magic_init();
275 | /*
276 | * #if 0 /* Set common mode voltage a bit higher for more margin 850 mv
277 | * * / e4k_commonmode_set(e4k, 4);
278 | *
279 | * /* Initialize DC offset lookup tables * /
280 | * e4k_dc_offset_gen_table(e4k);
281 | *
282 | * / * Enable time variant DC correction * / e4k_reg_write(e4k,
283 | * E4K_REG_DCTIME1, 0x01); e4k_reg_write(e4k, E4K_REG_DCTIME2, 0x01);
284 | * #endif
285 | */
286 |
287 | /* Set LNA mode to manual */
288 | e4k_reg_write((byte) E4K_REG_AGC4, 0x10); /* High threshold */
289 | e4k_reg_write((byte) E4K_REG_AGC5, 0x04); /* Low threshold */
290 | e4k_reg_write((byte) E4K_REG_AGC6, 0x1a); /* LNA calib + loop rate */
291 |
292 | e4k_reg_set_mask((byte) E4K_REG_AGC1, (char) E4K_AGC1_MOD_MASK,
293 | (char) E4K_AGC_MOD_SERIAL);
294 |
295 | /* Set Mixer Gain Control to manual */
296 | e4k_reg_set_mask((byte) E4K_REG_AGC7, (char) E4K_AGC7_MIX_GAIN_AUTO,
297 | (char) 0);
298 |
299 | /*
300 | * #if 0/* Enable LNA Gain enhancement * / e4k_reg_set_mask(e4k,
301 | * E4K_REG_AGC11, 0x7, E4K_AGC11_LNA_GAIN_ENH | (2 << 1));
302 | *
303 | * /* Enable automatic IF gain mode switching * / e4k_reg_set_mask(e4k,
304 | * E4K_REG_AGC8, 0x1, E4K_AGC8_SENS_LIN_AUTO); $infif
305 | */
306 |
307 | /* Use auto-gain as default */
308 | e4k_enable_manual_gain(false);
309 |
310 | /* Select moderate gain levels */
311 | e4k_if_gain_set((byte) 1, (byte) 6);
312 | e4k_if_gain_set(2, 0);
313 | e4k_if_gain_set(3, 0);
314 | e4k_if_gain_set(4, 0);
315 | e4k_if_gain_set(5, 9);
316 | e4k_if_gain_set(6, 9);
317 |
318 | /* Set the most narrow filter we can possibly use */
319 | // e4k_if_filter_bw_set(E4K_IF_FILTER_MIX, KHZ(1900));
320 | // e4k_if_filter_bw_set( E4K_IF_FILTER_RC, KHZ(1000));
321 | // e4k_if_filter_bw_set( E4K_IF_FILTER_CHAN, KHZ(2150));
322 | // e4k_if_filter_chan_enable(true);
323 |
324 | /* Disable time variant DC correction and LUT */
325 | e4k_reg_set_mask((byte) E4K_REG_DC5, (char) 0x03, (char) 0);
326 | e4k_reg_set_mask((byte) E4K_REG_DCTIME1, (char) 0x03, (char) 0);
327 | e4k_reg_set_mask((byte) E4K_REG_DCTIME2, (char) 0x03, (char) 0);
328 |
329 | return 0;
330 | }
331 |
332 | int find_stage_gain(byte stage, byte val) {
333 | byte[] arr;
334 | int i;
335 |
336 | if (stage >= (if_stage_gain.length))
337 | return -1;
338 |
339 | arr = if_stage_gain[stage];
340 |
341 | for (i = 0; i < if_stage_gain_len[stage]; i++) {
342 | if (arr[i] == val)
343 | return i;
344 | }
345 | return -1;
346 | }
347 |
348 | /*
349 | * ! \brief Set the gain of one of the IF gain stages \param [e4k] handle to
350 | * the tuner chip \param [stage] number of the stage (1..6) \param [value]
351 | * gain value in dB \returns 0 on success, negative in case of error
352 | */
353 | int e4k_if_gain_set(int stage, int value) {
354 | int rc;
355 | byte mask;
356 | // const struct reg_field *field;
357 |
358 | rc = find_stage_gain((byte) stage, (byte) value);
359 | if (rc < 0)
360 | return rc;
361 |
362 | /* compute the bit-mask for the given gain field */
363 | // field = if_stage_gain_regs[stage];
364 | // mask = width2mask[field.width] << field->shift;
365 |
366 | return 0;// e4k_reg_set_mask( field.reg, mask, rc << field.shift);
367 | }
368 |
369 | private int e4k_enable_manual_gain(boolean manual) {
370 | if (manual) {
371 | /* Set LNA mode to manual */
372 | e4k_reg_set_mask((byte) E4K_REG_AGC1, (char) E4K_AGC1_MOD_MASK,
373 | (char) E4K_AGC_MOD_SERIAL);
374 |
375 | /* Set Mixer Gain Control to manual */
376 | e4k_reg_set_mask((byte) E4K_REG_AGC7,
377 | (char) E4K_AGC7_MIX_GAIN_AUTO, (char) 0);
378 | } else {
379 | /* Set LNA mode to auto */
380 | e4k_reg_set_mask((byte) E4K_REG_AGC1, (char) E4K_AGC1_MOD_MASK,
381 | (char) E4K_AGC_MOD_IF_SERIAL_LNA_AUTON);
382 | /* Set Mixer Gain Control to auto */
383 | e4k_reg_set_mask((byte) E4K_REG_AGC7,
384 | (char) E4K_AGC7_MIX_GAIN_AUTO, (char) 1);
385 |
386 | e4k_reg_set_mask((byte) E4K_REG_AGC11, (char) 0x7, (char) 0);
387 | }
388 |
389 | return 0;
390 | }
391 |
392 | int unsigned_delta(int a, int b) {
393 | if (a > b)
394 | return a - b;
395 | else
396 | return b - a;
397 | }
398 |
399 | int closest_arr_idx(int arr[], int arr_size, int freq) {
400 | int i, bi = 0;
401 | int best_delta = 0xffffffff;
402 |
403 | /*
404 | * iterate over the array containing a list of the center frequencies,
405 | * selecting the closest one
406 | */
407 | for (i = 0; i < arr_size; i++) {
408 | int delta = unsigned_delta(freq, arr[i]);
409 | if (delta < best_delta) {
410 | best_delta = delta;
411 | bi = i;
412 | }
413 | }
414 |
415 | return bi;
416 | }
417 |
418 | int magic_init() {
419 | e4k_reg_write((byte) 0x7e, (byte) 0x01);
420 | e4k_reg_write((byte) 0x7f, (byte) 0xfe);
421 | e4k_reg_write((byte) 0x82, (byte) 0x00);
422 | e4k_reg_write((byte) 0x86, (byte) 0x50); /* polarity A */
423 | e4k_reg_write((byte) 0x87, (byte) 0x20);
424 | e4k_reg_write((byte) 0x88, (byte) 0x01);
425 | e4k_reg_write((byte) 0x9f, (byte) 0x7f);
426 | e4k_reg_write((byte) 0xa0, (byte) 0x07);
427 |
428 | return 0;
429 | }
430 | }
431 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/tuners/FC0012.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android.tuners;
2 |
3 | import java.io.IOException;
4 |
5 | public class FC0012 implements IRtlSdrTuner {
6 | private static final String TAG = FC0012.class.getSimpleName();
7 |
8 | @Override
9 | public int init(int param) throws IOException {
10 | // TODO Auto-generated method stub
11 | return 0;
12 | }
13 |
14 | @Override
15 | public int exit(int param) throws IOException {
16 | // TODO Auto-generated method stub
17 | return 0;
18 | }
19 |
20 | @Override
21 | public int set_freq(int param, long freq) throws IOException {
22 | // TODO Auto-generated method stub
23 | return 0;
24 | }
25 |
26 | @Override
27 | public int set_bw(int param, int bw) throws IOException {
28 | // TODO Auto-generated method stub
29 | return 0;
30 | }
31 |
32 | @Override
33 | public int set_gain(int param, int gain) throws IOException {
34 | // TODO Auto-generated method stub
35 | return 0;
36 | }
37 |
38 | @Override
39 | public int set_if_gain(int param, int stage, int gain) throws IOException {
40 | // TODO Auto-generated method stub
41 | return 0;
42 | }
43 |
44 | @Override
45 | public int set_gain_mode(int param, boolean manual) throws IOException {
46 | // TODO Auto-generated method stub
47 | return 0;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/tuners/FC0013.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android.tuners;
2 |
3 | import java.io.IOException;
4 |
5 | import android.util.Log;
6 |
7 | import com.rtlsdr.android.SdrSerialDriver;
8 |
9 | public class FC0013 implements IRtlSdrTuner {
10 | private static final String TAG = FC0013.class.getSimpleName();
11 | final int FC0013_I2C_ADDR = 0xc6;
12 | final int FC0013_CHECK_ADDR = 0x00;
13 | final int FC0013_CHECK_VAL = 0xa3;
14 | int[] fc0013_lna_gains = { -99, 0x02, -73, 0x03, -65, 0x05, -63, 0x04, -63,
15 | 0x00, -60, 0x07, -58, 0x01, -54, 0x06, 58, 0x0f, 61, 0x0e, 63,
16 | 0x0d, 65, 0x0c, 67, 0x0b, 68, 0x0a, 70, 0x09, 71, 0x08, 179, 0x17,
17 | 181, 0x16, 182, 0x15, 184, 0x14, 186, 0x13, 188, 0x12, 191, 0x11,
18 | 197, 0x10 };
19 |
20 | @Override
21 | public int init(int param) throws IOException {
22 | fc0013_init();
23 | return 0;
24 | }
25 |
26 | @Override
27 | public int exit(int param) throws IOException {
28 | // TODO Auto-generated method stub
29 | return 0;
30 | }
31 |
32 | @Override
33 | public int set_freq(int param, long freq) throws IOException {
34 | return fc0013_set_params((int) freq, 6000000);
35 | }
36 |
37 | @Override
38 | public int set_bw(int param, int bw) throws IOException {
39 | // TODO Auto-generated method stub
40 | return 0;
41 | }
42 |
43 | @Override
44 | public int set_gain(int param, int gain) throws IOException {
45 | return fc0013_set_lna_gain(gain);
46 | }
47 |
48 | @Override
49 | public int set_if_gain(int param, int stage, int gain) throws IOException {
50 | // TODO Auto-generated method stub
51 | return 0;
52 | }
53 |
54 | @Override
55 | public int set_gain_mode(int param, boolean manual) throws IOException {
56 | return fc0013_set_gain_mode(manual);
57 |
58 | }
59 |
60 | private int fc0013_writereg(byte reg, byte val) {
61 | byte[] data = new byte[2];
62 | data[0] = reg;
63 | data[1] = val;
64 |
65 | if (SdrSerialDriver.rtlsdr_i2c_write_fn((byte) FC0013_I2C_ADDR, data,
66 | (byte) 2) < 0)
67 | return -1;
68 |
69 | return 0;
70 | }
71 |
72 | private int fc0013_readreg(byte reg, byte[] val) {
73 | byte[] data = new byte[2];
74 | data[0] = reg;
75 |
76 | if (SdrSerialDriver.rtlsdr_i2c_write_fn((byte) FC0013_I2C_ADDR, data,
77 | (byte) 1) < 0)
78 | return -1;
79 |
80 | if (SdrSerialDriver.rtlsdr_i2c_read_fn((byte) FC0013_I2C_ADDR, data,
81 | (byte) 1) < 0)
82 | return -1;
83 |
84 | val[0] = data[0];
85 |
86 | return 0;
87 | }
88 |
89 | int fc0013_set_gain_mode(boolean manual) {
90 | int ret = 0;
91 | byte[] tmp = new byte[2];
92 |
93 | ret |= fc0013_readreg((byte) 0x0d, tmp);
94 |
95 | if (manual)
96 | tmp[0] |= (1 << 3);
97 | else
98 | tmp[0] &= ~(1 << 3);
99 |
100 | ret |= fc0013_writereg((byte) 0x0d, tmp[0]);
101 |
102 | /* set a fixed IF-gain for now */
103 | ret |= fc0013_writereg((byte) 0x13, (byte) 0x0a);
104 |
105 | return ret;
106 | }
107 |
108 | int fc0013_init() {
109 | int ret = 0;
110 | int i;
111 | byte[] reg = { 0x00, /* reg. 0x00: dummy */
112 | 0x09, /* reg. 0x01 */
113 | 0x16, /* reg. 0x02 */
114 | 0x00, /* reg. 0x03 */
115 | 0x00, /* reg. 0x04 */
116 | 0x17, /* reg. 0x05 */
117 | 0x02, /* reg. 0x06: LPF bandwidth */
118 | 0x0a, /* reg. 0x07: CHECK */
119 | (byte) 0xff, /*
120 | * reg. 0x08: AGC Clock divide by 256, AGC gain 1/256, Loop
121 | * Bw 1/8
122 | */
123 | 0x6e, /* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */
124 | (byte) 0xb8, /* reg. 0x0a: Disable LO Test Buffer */
125 | (byte) 0x82, /* reg. 0x0b: CHECK */
126 | (byte) 0xfc, /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
127 | 0x01, /* reg. 0x0d: AGC Not Forcing & LNA Forcing, may need 0x02 */
128 | 0x00, /* reg. 0x0e */
129 | 0x00, /* reg. 0x0f */
130 | 0x00, /* reg. 0x10 */
131 | 0x00, /* reg. 0x11 */
132 | 0x00, /* reg. 0x12 */
133 | 0x00, /* reg. 0x13 */
134 | 0x50, /*
135 | * reg. 0x14: DVB-t High Gain, UHF. Middle Gain: 0x48, Low Gain:
136 | * 0x40
137 | */
138 | 0x01, /* reg. 0x15 */
139 | };
140 | /*
141 | * #if 0 switch (rtlsdr_get_tuner_clock(dev)) { case FC_XTAL_27_MHZ:
142 | * case FC_XTAL_28_8_MHZ: reg[0x07] |= 0x20; break; case FC_XTAL_36_MHZ:
143 | * default: break; } #endif
144 | */
145 | reg[0x07] |= 0x20;
146 |
147 | // if (dev->dual_master)
148 | reg[0x0c] |= 0x02;
149 |
150 | for (i = 1; i < reg.length; i++) {
151 | ret = fc0013_writereg((byte) i, reg[i]);
152 | if (ret < 0)
153 | break;
154 | }
155 |
156 | return ret;
157 | }
158 |
159 | int fc0013_set_lna_gain(int gain) {
160 | int ret = 0;
161 | int i;
162 | byte[] tmp = new byte[1];
163 |
164 | ret |= fc0013_readreg((byte) 0x14, tmp);
165 |
166 | /* mask bits off */
167 | tmp[0] &= 0xe0;
168 |
169 | for (i = 0; i < fc0013_lna_gains.length / 2; i++) {
170 | if ((fc0013_lna_gains[i * 2] >= gain)
171 | || (i + 1 == (fc0013_lna_gains.length / 2))) {
172 | tmp[0] |= fc0013_lna_gains[i * 2 + 1];
173 | break;
174 | }
175 | }
176 |
177 | /* set gain */
178 | ret |= fc0013_writereg((byte) 0x14, tmp[0]);
179 |
180 | return ret;
181 | }
182 |
183 | int fc0013_set_params(int freq, int bandwidth) {
184 | int i, ret = 0;
185 | char[] reg = new char[7];
186 | byte am, pm, multi;
187 | long f_vco;
188 | int xtal_freq_div_2;
189 | char xin, xdiv;
190 | boolean vco_select = false;
191 | byte[] tmp = new byte[1];
192 |
193 | xtal_freq_div_2 = SdrSerialDriver.rtlsdr_get_tuner_clock() / 2;
194 |
195 | /* set VHF track */
196 | ret = fc0013_set_vhf_track(freq);
197 | if (ret < 0)
198 | return -1;
199 |
200 | if (freq < 300000000) {
201 | /* enable VHF filter */
202 | ret = fc0013_readreg((byte) 0x07, tmp);
203 | if (ret < 0)
204 | return -1;
205 | ret = fc0013_writereg((byte) 0x07, (byte) (tmp[0] | 0x10));
206 | if (ret < 0)
207 | return -1;
208 |
209 | /* disable UHF & disable GPS */
210 | ret = fc0013_readreg((byte) 0x14, tmp);
211 | if (ret < 0)
212 | return -1;
213 | ret = fc0013_writereg((byte) 0x14, (byte) (tmp[0] & 0x1f));
214 | if (ret < 0)
215 | return -1;
216 | } else if (freq <= 862000000) {
217 | /* disable VHF filter */
218 | ret = fc0013_readreg((byte) 0x07, tmp);
219 | if (ret < 0)
220 | return -1;
221 | ret = fc0013_writereg((byte) 0x07, (byte) (tmp[0] & 0xef));
222 | if (ret < 0)
223 | return -1;
224 | ;
225 |
226 | /* enable UHF & disable GPS */
227 | ret = fc0013_readreg((byte) 0x14, tmp);
228 | if (ret < 0)
229 | return -1;
230 | ;
231 | ret = fc0013_writereg((byte) 0x14, (byte) ((tmp[0] & 0x1f) | 0x40));
232 | if (ret < 0)
233 | return -1;
234 | ;
235 | } else {
236 | /* disable VHF filter */
237 | ret = fc0013_readreg((byte) 0x07, tmp);
238 | if (ret < 0)
239 | return -1;
240 | ret = fc0013_writereg((byte) 0x07, (byte) (tmp[0] & 0xef));
241 | if (ret < 0)
242 | return -1;
243 |
244 | /* disable UHF & enable GPS */
245 | ret = fc0013_readreg((byte) 0x14, tmp);
246 | if (ret < 0)
247 | return -1;
248 | ;
249 | ret = fc0013_writereg((byte) 0x14, (byte) ((tmp[0] & 0x1f) | 0x20));
250 | if (ret < 0)
251 | return -1;
252 | ;
253 | }
254 |
255 | /* select frequency divider and the frequency of VCO */
256 | if (freq < 37084000) { /* freq * 96 < 3560000000 */
257 | multi = 96;
258 | reg[5] = (char) 0x82;
259 | reg[6] = 0x00;
260 | } else if (freq < 55625000) { /* freq * 64 < 3560000000 */
261 | multi = 64;
262 | reg[5] = 0x02;
263 | reg[6] = 0x02;
264 | } else if (freq < 74167000) { /* freq * 48 < 3560000000 */
265 | multi = 48;
266 | reg[5] = 0x42;
267 | reg[6] = 0x00;
268 | } else if (freq < 111250000) { /* freq * 32 < 3560000000 */
269 | multi = 32;
270 | reg[5] = (char) 0x82;
271 | reg[6] = 0x02;
272 | } else if (freq < 148334000) { /* freq * 24 < 3560000000 */
273 | multi = 24;
274 | reg[5] = 0x22;
275 | reg[6] = 0x00;
276 | } else if (freq < 222500000) { /* freq * 16 < 3560000000 */
277 | multi = 16;
278 | reg[5] = 0x42;
279 | reg[6] = 0x02;
280 | } else if (freq < 296667000) { /* freq * 12 < 3560000000 */
281 | multi = 12;
282 | reg[5] = 0x12;
283 | reg[6] = 0x00;
284 | } else if (freq < 445000000) { /* freq * 8 < 3560000000 */
285 | multi = 8;
286 | reg[5] = 0x22;
287 | reg[6] = 0x02;
288 | } else if (freq < 593334000) { /* freq * 6 < 3560000000 */
289 | multi = 6;
290 | reg[5] = 0x0a;
291 | reg[6] = 0x00;
292 | } else if (freq < 950000000) { /* freq * 4 < 3800000000 */
293 | multi = 4;
294 | reg[5] = 0x12;
295 | reg[6] = 0x02;
296 | } else {
297 | multi = 2;
298 | reg[5] = 0x0a;
299 | reg[6] = 0x02;
300 | }
301 |
302 | f_vco = freq * multi;
303 |
304 | if (f_vco >= 3060000000L) {
305 | reg[6] |= 0x08;
306 | vco_select = true;
307 | }
308 |
309 | /* From divided value (XDIV) determined the FA and FP value */
310 | xdiv = (char) (f_vco / xtal_freq_div_2);
311 | if ((f_vco - xdiv * xtal_freq_div_2) >= (xtal_freq_div_2 / 2))
312 | xdiv++;
313 |
314 | pm = (byte) (xdiv / 8);
315 | am = (byte) (xdiv - (8 * pm));
316 |
317 | if (am < 2) {
318 | am += 8;
319 | pm--;
320 | }
321 |
322 | if (pm > 31) {
323 | reg[1] = (char) (am + (8 * (pm - 31)));
324 | reg[2] = 31;
325 | } else {
326 | reg[1] = (char) am;
327 | reg[2] = (char) pm;
328 | }
329 |
330 | if ((reg[1] > 15) || (reg[2] < 0x0b)) {
331 | Log.e("TAG", "[FC0013] no valid PLL combination found for " + freq
332 | + " HZ!");
333 | return -1;
334 | }
335 |
336 | /* fix clock out */
337 | reg[6] |= 0x20;
338 |
339 | /*
340 | * From VCO frequency determines the XIN ( fractional part of Delta
341 | * Sigma PLL) and divided value (XDIV)
342 | */
343 | xin = (char) ((f_vco - (f_vco / xtal_freq_div_2) * xtal_freq_div_2) / 1000);
344 | xin = (char) ((xin << 15) / (xtal_freq_div_2 / 1000));
345 | if (xin >= 16384)
346 | xin += 32768;
347 |
348 | reg[3] = (char) (xin >> 8);
349 | reg[4] = (char) (xin & 0xff);
350 |
351 | reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */
352 | switch (bandwidth) {
353 | case 6000000:
354 | reg[6] |= 0x80;
355 | break;
356 | case 7000000:
357 | reg[6] |= 0x40;
358 | break;
359 | case 8000000:
360 | default:
361 | break;
362 | }
363 |
364 | /* modified for Realtek demod */
365 | reg[5] |= 0x07;
366 |
367 | for (i = 1; i <= 6; i++) {
368 | ret = fc0013_writereg((byte) i, (byte) reg[i]);
369 | if (ret < 0)
370 | return -1;
371 | }
372 |
373 | ret = fc0013_readreg((byte) 0x11, tmp);
374 | if (ret < 0)
375 | return -1;
376 | if (multi == 64)
377 | ret = fc0013_writereg((byte) 0x11, (byte) (tmp[0] | 0x04));
378 | else
379 | ret = fc0013_writereg((byte) 0x11, (byte) (tmp[0] & 0xfb));
380 | if (ret < 0)
381 | return -1;
382 |
383 | /* VCO Calibration */
384 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x80);
385 | if (ret != 0)
386 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x00);
387 |
388 | /* VCO Re-Calibration if needed */
389 | if (ret != 0)
390 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x00);
391 |
392 | if (ret != 0) {
393 | // msleep(10);
394 | ret = fc0013_readreg((byte) 0x0e, tmp);
395 | }
396 | if (ret < 0)
397 | return -1;
398 |
399 | /* vco selection */
400 | tmp[0] &= 0x3f;
401 |
402 | if (vco_select) {
403 | if (tmp[0] > 0x3c) {
404 | reg[6] &= ~0x08;
405 | ret = fc0013_writereg((byte) 0x06, (byte) reg[6]);
406 | if (ret != 0)
407 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x80);
408 | if (ret != 0)
409 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x00);
410 | }
411 | } else {
412 | if (tmp[0] < 0x02) {
413 | reg[6] |= 0x08;
414 | ret = fc0013_writereg((byte) 0x06, (byte) reg[6]);
415 | if (ret != 0)
416 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x80);
417 | if (ret != 0)
418 | ret = fc0013_writereg((byte) 0x0e, (byte) 0x00);
419 | }
420 | }
421 |
422 | // exit:
423 | return ret;
424 | }
425 |
426 | private int fc0013_set_vhf_track(int freq) {
427 | int ret;
428 |
429 | byte[] tmp = new byte[1];
430 |
431 | ret = fc0013_readreg((byte) 0x1d, tmp);
432 | if (ret != 0)
433 | return -1;
434 | tmp[0] &= 0xe3;
435 | if (freq <= 177500000) { /* VHF Track: 7 */
436 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x1c));
437 | } else if (freq <= 184500000) { /* VHF Track: 6 */
438 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x18));
439 | } else if (freq <= 191500000) { /* VHF Track: 5 */
440 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x14));
441 | } else if (freq <= 198500000) { /* VHF Track: 4 */
442 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x10));
443 | } else if (freq <= 205500000) { /* VHF Track: 3 */
444 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x0c));
445 | } else if (freq <= 219500000) { /* VHF Track: 2 */
446 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x08));
447 | } else if (freq < 300000000) { /* VHF Track: 1 */
448 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x04));
449 | } else { /* UHF and GPS */
450 | ret = fc0013_writereg((byte) 0x1d, (byte) (tmp[0] | 0x1c));
451 | }
452 |
453 | // error_out:
454 | return ret;
455 | }
456 | }
457 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/tuners/FC2580.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android.tuners;
2 |
3 | import java.io.IOException;
4 |
5 | public class FC2580 implements IRtlSdrTuner {
6 |
7 | @Override
8 | public int init(int param) throws IOException {
9 | // TODO Auto-generated method stub
10 | return 0;
11 | }
12 |
13 | @Override
14 | public int exit(int param) throws IOException {
15 | // TODO Auto-generated method stub
16 | return 0;
17 | }
18 |
19 | @Override
20 | public int set_freq(int param, long freq) throws IOException {
21 | // TODO Auto-generated method stub
22 | return 0;
23 | }
24 |
25 | @Override
26 | public int set_bw(int param, int bw) throws IOException {
27 | // TODO Auto-generated method stub
28 | return 0;
29 | }
30 |
31 | @Override
32 | public int set_gain(int param, int gain) throws IOException {
33 | // TODO Auto-generated method stub
34 | return 0;
35 | }
36 |
37 | @Override
38 | public int set_if_gain(int param, int stage, int gain) throws IOException {
39 | // TODO Auto-generated method stub
40 | return 0;
41 | }
42 |
43 | @Override
44 | public int set_gain_mode(int param, boolean manual) throws IOException {
45 | // TODO Auto-generated method stub
46 | return 0;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/com/rtlsdr/android/tuners/IRtlSdrTuner.java:
--------------------------------------------------------------------------------
1 | package com.rtlsdr.android.tuners;
2 |
3 | import java.io.IOException;
4 |
5 | public interface IRtlSdrTuner {
6 | int init(int param) throws IOException;
7 |
8 | int exit(int param) throws IOException;
9 |
10 | int set_freq(int param, long freq /* Hz */) throws IOException;
11 |
12 | int set_bw(int param, int bw /* Hz */) throws IOException;
13 |
14 | int set_gain(int param, int gain /* tenth dB */) throws IOException;
15 |
16 | int set_if_gain(int param, int stage, int gain /* tenth dB */)
17 | throws IOException;
18 |
19 | int set_gain_mode(int param, boolean manual) throws IOException;
20 | }
21 |
--------------------------------------------------------------------------------