summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING340
-rw-r--r--LICENSING11
-rw-r--r--Makefile13
-rw-r--r--README52
-rw-r--r--TODO23
-rw-r--r--include/rfid/rfid.h12
-rw-r--r--include/rfid/rfid_asic.h43
-rw-r--r--include/rfid/rfid_asic_rc632.h141
-rw-r--r--include/rfid/rfid_layer2.h56
-rw-r--r--include/rfid/rfid_layer2_iso14443a.h93
-rw-r--r--include/rfid/rfid_layer2_iso14443b.h83
-rw-r--r--include/rfid/rfid_protocol.h53
-rw-r--r--include/rfid/rfid_protocol_tcl.h65
-rw-r--r--include/rfid/rfid_reader.h50
-rw-r--r--include/rfid/rfid_reader_cm5121.h21
-rw-r--r--openct-escape.c120
-rw-r--r--rc632.h209
-rw-r--r--rfid.c39
-rw-r--r--rfid_asic_rc632.c833
-rw-r--r--rfid_asic_rc632_14443a.c393
-rw-r--r--rfid_asic_rc632_14443b.c69
-rw-r--r--rfid_asic_rc632_mifare.c25
-rw-r--r--rfid_iso14443_common.c41
-rw-r--r--rfid_iso14443_common.h11
-rw-r--r--rfid_layer2.c59
-rw-r--r--rfid_layer2_iso14443a.c277
-rw-r--r--rfid_layer2_iso14443b.c309
-rw-r--r--rfid_proto_tcl.c448
-rw-r--r--rfid_protocol.c59
-rw-r--r--rfid_reader.c48
-rw-r--r--rfid_reader_cm5121.c276
31 files changed, 4272 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/LICENSING b/LICENSING
new file mode 100644
index 0000000..0ebe6bb
--- /dev/null
+++ b/LICENSING
@@ -0,0 +1,11 @@
+librfid is licensed under GNU General Public License, Version 2 as published
+by the Free Software Foundation (see the file COPYING).
+
+This means that as soon as you wish to distribute a program that links to
+librfid, that other program has to be licensed under the GPL or a compatible
+license, too.
+
+However, an alternative (royalty-based) licensing is possible. If you want to
+create a proprieatary program based on librfid, contact Harald Welte
+<hwelte@hmw-consulting.de> for licensing details.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bcf5f44
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CFLAGS:=-Wall -g -I/usr/local/include -Iinclude
+LDFLAGS:=-lopenct -lusb
+
+all: openct-escape
+
+openct-escape: openct-escape.o rfid_layer2.o rfid_layer2_iso14443a.o rfid_layer2_iso14443b.o rfid_asic_rc632.o rfid_reader_cm5121.o rfid.o rfid_protocol.o rfid_proto_tcl.o rfid_iso14443_common.o rfid_reader.o
+ $(CC) $(LDFLAGS) -o $@ $^
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $^
+
+clean:
+ rm -f *.o openct-escape
diff --git a/README b/README
new file mode 100644
index 0000000..c67a48a
--- /dev/null
+++ b/README
@@ -0,0 +1,52 @@
+librfid - low-level RFID access library
+(C) 2005 by Harald Welte <laforge@gnumonks.org>
+======================================================================
+
+This library intends to provide a reader- and (as much as possible)
+PICC / tag independent API for RFID applications.
+
+1. Supported Prodocols:
+
+At this early stage of implementaition, it offers only ISO 14443-2, ISO 14443-3
+A and B as well as ISO 14443-4 (T=CL) support. Other protocols, both open
+(such as ISO 15693) and proprietary are to be added as soon as I find some more
+time.
+
+2. Supported Readers:
+
+At this time only the Omnikey Cardman 5121 reader is supported.
+
+The cm5121 is a relatively stupid piece of hardware. Basically a contact-based
+cm3121 that was enhanced by putting a Philips CL RC632 reader ASIC next to it.
+There is no RFID protocol implementation on the cm5121, everything is done on
+the host (PC) software. Four primitives (read/write byte/fifo) are provided
+via simple PC_to_RDR_Escape CCID messages.
+
+This makes it the ideal device to learn and play with RFID, since you don't
+have any (proprietary) software interfere and puts you in full control of
+everything.
+
+Support for more devices shouldn't be too difficult to add, provided the
+devices are stupid enough. More sophisticated readers like Integrated
+Engineering or Philips Pegoda do much of the protocol handling in firmware on a
+Microcontroller. This makes them (at least till now) faster, but also of
+limited use, especially in education and research.
+
+So if you happen to run into any other dumb RFID readers, especially those
+based on Philips CL RC531 and RC632, adding support should be very
+straightforward. If you want to contract me for implementing a driver backend,
+don't hesitate to contact me.
+
+3. Installation
+
+In order to run librfid, you need to provide a PC_to_RDR_Escape function to it.
+This is the low-level transport function for communicating. Usually that function would point to a CCID device driver.
+
+My svn repository at
+https://svn.gnumonks.org/trunk/omnikey_cardman/new/userspace/ has an openct
+fork with a modified CCID driver. It allows you to use the contact based part
+via PC/SC, CT-API, and the contactless part via librfid simultaneously.
+
+
+-- Harald Welte <laforge@gnumonks.org>
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5d50d15
--- /dev/null
+++ b/TODO
@@ -0,0 +1,23 @@
+rc632:
+- fix handling of timeout (program timer of RC632)
+
+iso14443a:
+- test anticollision, resolve remaining bugs
+
+iso14443b:
+- implement 'option 2' frame markers
+- test anticollission (need multiple tags)
+
+tcl:
+- implement chaining
+- implement wait time extension
+
+openct:
+- add ifdhandler driver
+
+other:
+- implementation of various tags
+- documentation
+- homepage
+- mailinglist(s)
+- move to new 'librfid' svn repository
diff --git a/include/rfid/rfid.h b/include/rfid/rfid.h
new file mode 100644
index 0000000..bf8d799
--- /dev/null
+++ b/include/rfid/rfid.h
@@ -0,0 +1,12 @@
+#ifndef _RFID_H
+#define _RFID_H
+
+#include <stdio.h>
+
+
+#define DEBUGP(x, args ...) fprintf(stderr, "%s(%d):%s: " x, __FILE__, __LINE__, __FUNCTION__, ## args)
+extern const char *rfid_hexdump(const void *data, unsigned int len);
+
+int rfid_init();
+
+#endif /* _RFID_H */
diff --git a/include/rfid/rfid_asic.h b/include/rfid/rfid_asic.h
new file mode 100644
index 0000000..e336d01
--- /dev/null
+++ b/include/rfid/rfid_asic.h
@@ -0,0 +1,43 @@
+#ifndef _RFID_ASIC_H
+#define _RFID_ASIC_H
+
+#include <rfid/rfid_asic_rc632.h>
+
+struct rfid_asic_transport {
+ char *name;
+ union {
+ struct rfid_asic_rc632_transport rc632;
+ } priv;
+};
+
+struct rfid_asic_transport_handle {
+ void *data; /* handle to stuff like even lower layers */
+
+ struct rfid_asic_transport *rat;
+};
+
+
+struct rfid_asic_handle {
+ struct rfid_asic_transport_handle *rath;
+ unsigned int fc;
+ unsigned int mtu;
+ unsigned int mru;
+
+ union {
+ struct rfid_asic_rc632_handle rc632;
+ //struct rfid_asic_rc531_handle rc531;
+ } priv;
+ struct rfid_asic *asic;
+};
+
+
+struct rfid_asic {
+ char *name;
+ unsigned int fc; /* carrier frequency */
+ union {
+ struct rfid_asic_rc632 rc632;
+ //struct rfid_asic_rc531 rc531;
+ } priv;
+};
+
+#endif /* _RFID_ASIC_H */
diff --git a/include/rfid/rfid_asic_rc632.h b/include/rfid/rfid_asic_rc632.h
new file mode 100644
index 0000000..f4c9fa1
--- /dev/null
+++ b/include/rfid/rfid_asic_rc632.h
@@ -0,0 +1,141 @@
+#ifndef _RFID_ASIC_RC632_H
+#define _RFID_ASIC_RC632_H
+
+struct rfid_asic_transport_handle;
+
+struct rfid_asic_rc632_transport {
+ struct {
+ int (*reg_write)(struct rfid_asic_transport_handle *rath,
+ unsigned char reg,
+ unsigned char value);
+ int (*reg_read)(struct rfid_asic_transport_handle *rath,
+ unsigned char reg,
+ unsigned char *value);
+ int (*fifo_write)(struct rfid_asic_transport_handle *rath,
+ unsigned char len,
+ const unsigned char *buf,
+ unsigned char flags);
+ int (*fifo_read)(struct rfid_asic_transport_handle *rath,
+ unsigned char len,
+ unsigned char *buf);
+ } fn;
+};
+
+struct rfid_asic_handle;
+
+struct iso14443a_atqua;
+struct iso14443a_anticol_cmd;
+
+struct rfid_asic_rc632 {
+ struct {
+ int (*power_up)(struct rfid_asic_handle *h);
+ int (*power_down)(struct rfid_asic_handle *h);
+ int (*turn_on_rf)(struct rfid_asic_handle *h);
+ int (*turn_off_rf)(struct rfid_asic_handle *h);
+ int (*transcieve)(struct rfid_asic_handle *h,
+ const unsigned char *tx_buf,
+ unsigned int tx_len,
+ unsigned char *rx_buf,
+ unsigned int *rx_len,
+ unsigned int timeout,
+ unsigned int flags);
+ struct {
+ int (*init)(struct rfid_asic_handle *h);
+ int (*transcieve_sf)(struct rfid_asic_handle *h,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa);
+ int (*transcieve_acf)(struct rfid_asic_handle *h,
+ struct iso14443a_anticol_cmd *cmd,
+ unsigned int *bit_of_col);
+ } iso14443a;
+ struct {
+ int (*init)(struct rfid_asic_handle *h);
+ } iso14443b;
+ } fn;
+};
+
+struct rc632_transport_handle {
+};
+
+/* A handle to a specific RC632 chip */
+struct rfid_asic_rc632_handle {
+ struct rc632_transport_handle th;
+};
+
+int
+rc632_reg_write(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char val);
+
+int
+rc632_reg_read(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char *val);
+int
+rc632_fifo_write(struct rfid_asic_handle *handle,
+ unsigned char len,
+ const unsigned char *buf,
+ unsigned char flags);
+
+int
+rc632_fifo_read(struct rfid_asic_handle *handle,
+ unsigned char len,
+ unsigned char *buf);
+
+int
+rc632_set_bits(struct rfid_asic_handle *handle, unsigned char reg,
+ unsigned char val);
+
+int
+rc632_clear_bits(struct rfid_asic_handle *handle, unsigned char reg,
+ unsigned char val);
+
+
+int
+rc632_turn_on_rf(struct rfid_asic_handle *handle);
+
+
+int
+rc632_turn_off_rf(struct rfid_asic_handle *handle);
+
+int
+rc632_power_up(struct rfid_asic_handle *handle);
+
+int
+rc632_power_down(struct rfid_asic_handle *handle);
+
+
+int
+rc632_wait_idle(struct rfid_asic_handle *handle, unsigned int time);
+
+int
+rc632_transmit(struct rfid_asic_handle *handle,
+ const unsigned char *buf,
+ unsigned char len,
+ unsigned int timeout);
+
+int
+rc632_transcieve(struct rfid_asic_handle *handle,
+ const unsigned char *tx_buf,
+ unsigned char tx_len,
+ unsigned char *rx_buf,
+ unsigned char *rx_len,
+ unsigned int timer,
+ unsigned int toggle);
+
+int
+rc632_read_eeprom(struct rfid_asic_handle *handle);
+
+
+int
+rc632_calc_crc16_from(struct rfid_asic_handle *handle);
+
+int
+rc632_register_dump(struct rfid_asic_handle *handle, unsigned char *buf);
+
+
+//struct rfid_asic_handle * rc632_open(struct rc632_transport *transport, void *data);
+
+
+extern struct rfid_asic rc632;
+#endif
diff --git a/include/rfid/rfid_layer2.h b/include/rfid/rfid_layer2.h
new file mode 100644
index 0000000..40b9bff
--- /dev/null
+++ b/include/rfid/rfid_layer2.h
@@ -0,0 +1,56 @@
+#ifndef _RFID_LAYER2_H
+#define _RFID_LAYER2_H
+
+struct rfid_layer2_handle;
+struct rfid_reader_handle;
+
+#include <rfid/rfid_layer2_iso14443a.h>
+#include <rfid/rfid_layer2_iso14443b.h>
+
+
+struct rfid_layer2 {
+ unsigned int id;
+ char *name;
+
+ struct {
+ struct rfid_layer2_handle *(*init)(struct rfid_reader_handle *h);
+ int (*open)(struct rfid_layer2_handle *h);
+ int (*transcieve)(struct rfid_layer2_handle *h,
+ const unsigned char *tx_buf,
+ unsigned int tx_len, unsigned char *rx_buf,
+ unsigned int *rx_len, unsigned int timeout,
+ unsigned int flags);
+ int (*close)(struct rfid_layer2_handle *h);
+ int (*fini)(struct rfid_layer2_handle *h);
+ } fn;
+ struct rfid_layer2 *next;
+};
+
+struct rfid_layer2_handle {
+ struct rfid_reader_handle *rh;
+ union {
+ struct iso14443a_handle iso14443a;
+ struct iso14443b_handle iso14443b;
+ //struct iso15693_handle iso15693;
+ } priv;
+ struct rfid_layer2 *l2;
+};
+
+enum rfid_layer2_id {
+ RFID_LAYER2_NONE,
+ RFID_LAYER2_ISO14443A,
+ RFID_LAYER2_ISO14443B,
+ RFID_LAYER2_ISO15693,
+};
+
+struct rfid_layer2_handle *rfid_layer2_init(struct rfid_reader_handle *rh,
+ unsigned int id);
+int rfid_layer2_open(struct rfid_layer2_handle *l2h);
+int rfid_layer2_transcieve(struct rfid_layer2_handle *l2h,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags);
+int rfid_layer2_close(struct rfid_layer2_handle *l2h);
+int rfid_layer2_fini(struct rfid_layer2_handle *l2h);
+
+#endif
diff --git a/include/rfid/rfid_layer2_iso14443a.h b/include/rfid/rfid_layer2_iso14443a.h
new file mode 100644
index 0000000..400f951
--- /dev/null
+++ b/include/rfid/rfid_layer2_iso14443a.h
@@ -0,0 +1,93 @@
+#ifndef _RFID_ISO14443A_H
+#define _RFID_ISO14443A_H
+
+#include <sys/types.h>
+
+/* protocol definitions */
+
+/* ISO 14443-3, Chapter 6.3.1 */
+enum iso14443a_sf_cmd {
+ ISO14443A_SF_CMD_REQA = 0x26,
+ ISO14443A_SF_CMD_WUPA = 0x52,
+ ISO14443A_SF_CMD_OPT_TIMESLOT = 0x35, /* Annex C */
+ /* 40 to 4f and 78 to 7f: proprietary */
+};
+
+struct iso14443a_atqa {
+ u_int8_t bf_anticol:5,
+ rfu1:1,
+ uid_size:2;
+ u_int8_t proprietary:4,
+ rfu2:4;
+};
+
+#define ISO14443A_HLTA 0x5000
+
+/* ISO 14443-3, Chapter 6.3.2 */
+struct iso14443a_anticol_cmd {
+ unsigned char sel_code;
+ unsigned char nvb;
+ unsigned char uid_bits[5];
+};
+
+enum iso14443a_anticol_sel_code {
+ ISO14443A_AC_SEL_CODE_CL1 = 0x93,
+ ISO14443A_AC_SEL_CODE_CL2 = 0x95,
+ ISO14443A_AC_SEL_CODE_CL3 = 0x97,
+};
+
+#define ISO14443A_BITOFCOL_NONE 0xffffffff
+
+struct iso14443a_handle;
+
+struct iso14443a_transport {
+ unsigned char *name;
+
+ struct {
+ int (*init)(struct iso14443a_handle *handle);
+ int (*fini)(struct iso14443a_handle *handle);
+
+ int (*transcieve_sf)(struct iso14443a_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa);
+ int (*transcieve_acf)(struct iso14443a_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col);
+ int (*transcieve)(struct iso14443a_handle *handle,
+ const unsigned char *tx_buf,
+ unsigned int tx_len,
+ unsigned char *rx_buf,
+ unsigned int *rx_len);
+ } fn;
+
+ union {
+ } priv;
+};
+
+struct iso14443a_handle {
+ unsigned int state;
+ unsigned int level;
+ unsigned int tcl_capable;
+};
+
+enum iso14443a_level {
+ ISO14443A_LEVEL_NONE,
+ ISO14443A_LEVEL_CL1,
+ ISO14443A_LEVEL_CL2,
+ ISO14443A_LEVEL_CL3,
+};
+
+enum iso14443a_state {
+ ISO14443A_STATE_ERROR,
+ ISO14443A_STATE_NONE,
+ ISO14443A_STATE_REQA_SENT,
+ ISO14443A_STATE_ATQA_RCVD,
+ ISO14443A_STATE_NO_BITFRAME_ANTICOL,
+ ISO14443A_STATE_ANTICOL_RUNNING,
+ ISO14443A_STATE_SELECTED,
+};
+
+#include <rfid/rfid_layer2.h>
+struct rfid_layer2 rfid_layer2_iso14443a;
+
+#endif /* _ISO14443A_H */
diff --git a/include/rfid/rfid_layer2_iso14443b.h b/include/rfid/rfid_layer2_iso14443b.h
new file mode 100644
index 0000000..72e6155
--- /dev/null
+++ b/include/rfid/rfid_layer2_iso14443b.h
@@ -0,0 +1,83 @@
+#ifndef _RFID_LAYER2_ISO14443B_H
+#define _RFID_LAYER2_ISO14443B_H
+
+struct iso14443b_atqb {
+ unsigned char fifty;
+ unsigned char pupi[4];
+ unsigned char app_data[4];
+ struct {
+ unsigned char bit_rate_capability;
+ unsigned char protocol_type:4,
+ max_frame_size:4;
+ unsigned char fo:2,
+ adc:2,
+ fwi:4;
+ } protocol_info;
+};
+
+struct iso14443b_attrib_hdr {
+ unsigned char one_d;
+ unsigned char identifier[4];
+ struct {
+ unsigned char rfu:2,
+ sof:1,
+ eof:1,
+ min_tr1:2,
+ min_tr0:2;
+ } param1;
+ struct {
+ unsigned char fsdi:4,
+ spd_out:2,
+ spd_in:2;
+ } param2;
+ struct {
+ unsigned char protocol_type:4,
+ rfu:4;
+ } param3;
+ struct {
+ unsigned char cid:4,
+ rfu:4;
+ } param4;
+};
+
+struct iso14443b_handle {
+ unsigned int tcl_capable; /* do we support T=CL */
+
+ unsigned char pupi[4]; /* Pseudo-Unique PICC Identifier */
+ unsigned int cid; /* Card ID */
+
+ unsigned int fsc; /* max. frame size card */
+ unsigned int fsd; /* max. frame size reader */
+
+ unsigned int fwt; /* frame waiting time */
+
+ unsigned int mbl; /* maximum buffer length */
+
+ unsigned int tr0; /* pcd-eof to picc-subcarrier-on */
+ unsigned int tr1; /* picc-subcarrier-on to picc-sof */
+
+ unsigned int flags;
+ unsigned int state;
+};
+
+enum {
+ ISO14443B_CID_SUPPORTED = 0x01,
+ ISO14443B_NAD_SUPPORTED = 0x02,
+};
+
+enum {
+ ISO14443B_STATE_ERROR,
+ ISO14443B_STATE_NONE,
+ ISO14443B_STATE_REQB_SENT,
+ ISO14443B_STATE_ATQB_RCVD,
+ ISO14443B_STATE_ATTRIB_SENT,
+ ISO14443B_STATE_SELECTED,
+ ISO14443B_STATE_HLTB_SENT,
+ ISO14443B_STATE_HALTED,
+};
+
+
+#include <rfid/rfid_layer2.h>
+struct rfid_layer2 rfid_layer2_iso14443b;
+
+#endif
diff --git a/include/rfid/rfid_protocol.h b/include/rfid/rfid_protocol.h
new file mode 100644
index 0000000..93b89c3
--- /dev/null
+++ b/include/rfid/rfid_protocol.h
@@ -0,0 +1,53 @@
+#ifndef _RFID_PROTOCOL_H
+#define _RFID_PROTOCOL_H
+
+#include <rfid/rfid_layer2.h>
+
+#include <rfid/rfid_protocol_tcl.h>
+
+struct rfid_protocol_handle;
+
+struct rfid_protocol {
+ struct rfid_protocol *next;
+ unsigned int id;
+ char *name;
+ struct {
+ struct rfid_protocol_handle *(*init)(struct rfid_layer2_handle *l2h);
+ int (*open)(struct rfid_protocol_handle *ph);
+ int (*close)(struct rfid_protocol_handle *ph);
+ int (*fini)(struct rfid_protocol_handle *ph);
+ int (*transcieve)(struct rfid_protocol_handle *ph,
+ const unsigned char *tx_buf,
+ unsigned int tx_len,
+ unsigned char *rx_buf,
+ unsigned int *rx_len,
+ unsigned int timeout,
+ unsigned int flags);
+ } fn;
+};
+
+struct rfid_protocol_handle {
+ struct rfid_layer2_handle *l2h;
+ union {
+ struct tcl_handle tcl;
+ } priv;
+ struct rfid_protocol *proto;
+};
+
+struct rfid_protocol_handle *
+rfid_protocol_init(struct rfid_layer2_handle *l2h, unsigned int id);
+int rfid_protocol_open(struct rfid_protocol_handle *ph);
+int rfid_protocol_transcieve(struct rfid_protocol_handle *ph,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags);
+int rfid_protocol_fini(struct rfid_protocol_handle *ph);
+int rfid_protocol_close(struct rfid_protocol_handle *ph);
+
+int rfid_protocol_register(struct rfid_protocol *p);
+
+enum rfid_protocol_id {
+ RFID_PROTOCOL_UNKNOWN,
+ RFID_PROTOCOL_TCL,
+};
+#endif
diff --git a/include/rfid/rfid_protocol_tcl.h b/include/rfid/rfid_protocol_tcl.h
new file mode 100644
index 0000000..b913e80
--- /dev/null
+++ b/include/rfid/rfid_protocol_tcl.h
@@ -0,0 +1,65 @@
+#ifndef _RFID_PROTOCOL_TCL_H
+#define _RFID_PROTOCOL_TCL_H
+
+enum tcl_transport_rate {
+ TCL_RATE_106 = 0x01,
+ TCL_RATE_212 = 0x02,
+ TCL_RATE_424 = 0x04,
+ TCL_RATE_848 = 0x08,
+};
+
+enum tcl_transport_transcieve_flags {
+ TCL_TRANSP_F_TX_CRC = 0x01, /* transport adds TX CRC */
+ TCL_TRANSP_F_RX_CRC = 0x02,
+};
+
+
+struct tcl_handle {
+ /* derived from ats */
+ unsigned char *historical_bytes; /* points into ats */
+ unsigned int historical_len;
+
+ unsigned int fsc; /* max frame size accepted by card */
+ unsigned int fsd; /* max frame size accepted by reader */
+ unsigned int fwt; /* frame waiting time */
+ unsigned char ta; /* divisor information */
+ unsigned char sfgt; /* start-up frame guard time */
+
+ /* otherwise determined */
+ unsigned int cid; /* Card ID */
+ unsigned int nad; /* Node Address */
+
+ unsigned int flags;
+ unsigned int state; /* protocol state */
+
+ unsigned int ats_len;
+ unsigned char ats[0];
+};
+
+enum tcl_handle_flags {
+ TCL_HANDLE_F_NAD_SUPPORTED = 0x0001,
+ TCL_HANDLE_F_CID_SUPPORTED = 0x0002,
+ TCL_HANDLE_F_NAD_USED = 0x0010,
+ TCL_HANDLE_F_CID_USED = 0x0020,
+};
+
+
+enum tcl_pcb_bits {
+ TCL_PCB_CID_FOLLOWING = 0x08,
+ TCL_PCB_NAD_FOLLOWING = 0x04,
+};
+
+enum tcl_pcd_state {
+ TCL_STATE_NONE = 0x00,
+ TCL_STATE_INITIAL,
+ TCL_STATE_RATS_SENT, /* waiting for ATS */
+ TCL_STATE_ATS_RCVD, /* ATS received */
+ TCL_STATE_PPS_SENT, /* waiting for PPS response */
+ TCL_STATE_ESTABLISHED, /* xchg transparent data */
+ TCL_STATE_DESELECT_SENT, /* waiting for DESELECT response */
+ TCL_STATE_DESELECTED, /* card deselected or HLTA'd */
+};
+
+struct rfid_protocol rfid_protocol_tcl;
+
+#endif
diff --git a/include/rfid/rfid_reader.h b/include/rfid/rfid_reader.h
new file mode 100644
index 0000000..d6ad3a1
--- /dev/null
+++ b/include/rfid/rfid_reader.h
@@ -0,0 +1,50 @@
+#ifndef _RFID_READER_H
+#define _RFID_READER_H
+
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+struct rfid_reader_handle;
+
+struct rfid_reader {
+ char *name;
+ unsigned int id;
+ int (*transcieve)(struct rfid_reader_handle *h,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags);
+ struct rfid_reader_handle * (*open)(void *data);
+ int (*close)(void *data);
+
+ struct rfid_14443a_reader {
+ int (*init)(struct rfid_reader_handle *h);
+ int (*transcieve_sf)(struct rfid_reader_handle *h,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa);
+ int (*transcieve_acf)(struct rfid_reader_handle *h,
+ struct iso14443a_anticol_cmd *cmd,
+ unsigned int *bit_of_col);
+ } iso14443a;
+ struct rfid_14443b_reader {
+ int (*init)(struct rfid_reader_handle *rh);
+ } iso14443b;
+ struct rfid_15693_reader {
+
+ } iso15693;
+ struct rfid_reader *next;
+};
+
+enum rfid_reader_id {
+ RFID_READER_CM5121,
+ RFID_READER_PEGODA,
+};
+
+struct rfid_reader_handle {
+ struct rfid_asic_handle *ah;
+
+ union {
+
+ } priv;
+ struct rfid_reader *reader;
+};
+#endif
diff --git a/include/rfid/rfid_reader_cm5121.h b/include/rfid/rfid_reader_cm5121.h
new file mode 100644
index 0000000..8d9a312
--- /dev/null
+++ b/include/rfid/rfid_reader_cm5121.h
@@ -0,0 +1,21 @@
+#ifndef _RFID_READER_CM5121_H
+#define _RFID_READER_CM5121_H
+
+#define CM5121_CW_CONDUCTANCE 0x3f
+#define CM5121_MOD_CONDUCTANCE 0x3f
+#define CM5121_14443A_BITPHASE 0xa9
+#define CM5121_14443A_THRESHOLD 0xff
+
+#define CM5121_14443B_BITPHASE 0xad
+#define CM5121_14443B_THRESHOLD 0xff
+
+
+extern int
+PC_to_RDR_Escape(void *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len);
+
+extern struct rfid_reader rfid_reader_cm5121;
+// extern struct rfid_asic_transport cm5121_ccid;
+
+#endif
diff --git a/openct-escape.c b/openct-escape.c
new file mode 100644
index 0000000..ed28c8d
--- /dev/null
+++ b/openct-escape.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openct/openct.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_reader_cm5121.h>
+
+static int slot = 1;
+static ct_handle *h;
+static ct_lock_handle lock;
+
+static struct rfid_reader_handle *rh;
+static struct rfid_layer2_handle *l2h;
+static struct rfid_protocol_handle *ph;
+
+
+/* this is the sole function required by rfid_reader_cm5121.c */
+int
+PC_to_RDR_Escape(void *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len)
+{
+ ct_handle *h = (ct_handle *) handle;
+ int rc;
+
+ rc = ct_card_transact(h, 1, tx_buf, tx_len, rx_buf, *rx_len);
+ if (rc >= 0) {
+ *rx_len = rc;
+ return 0;
+ }
+
+ return rc;
+}
+
+
+
+static int init()
+{
+ unsigned char buf[0x3f];
+ unsigned char atr[64];
+ unsigned
+ int rc;
+
+ h = ct_reader_connect(0);
+ if (!h)
+ return -1;
+
+ printf("acquiring card lock\n");
+ rc = ct_card_lock(h, slot, IFD_LOCK_EXCLUSIVE, &lock);
+ if (rc < 0) {
+ fprintf(stderr, "error, no card lock\n");
+ return -1;
+ }
+
+ rc = ct_card_reset(h, slot, atr, sizeof(atr));
+ if (rc < 0) {
+ fprintf(stderr, "error, can't reset virtual card\n");
+ return -1;
+ }
+
+ rfid_init();
+
+ printf("opening reader handle\n");
+ rh = rfid_reader_open(h, RFID_READER_CM5121);
+ if (!rh) {
+ fprintf(stderr, "error, no cm5121 handle\n");
+ return -1;
+ }
+
+ printf("opening layer2 handle\n");
+ //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A);
+ l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B);
+ if (!l2h) {
+ fprintf(stderr, "error during iso14443a_init\n");
+ return -1;
+ }
+
+ //rc632_register_dump(rh->ah, buf);
+
+ printf("running layer2 anticol\n");
+ rc = rfid_layer2_open(l2h);
+ if (rc < 0) {
+ fprintf(stderr, "error during layer2_open\n");
+ return rc;
+ }
+
+ printf("running layer3 (ats)\n");
+ ph = rfid_protocol_init(l2h, RFID_PROTOCOL_TCL);
+ if (!ph) {
+ fprintf(stderr, "error during protocol_init\n");
+ return -1;
+ }
+ if (rfid_protocol_open(ph) < 0) {
+ fprintf(stderr, "error during protocol_open\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+ int rc;
+ char buf[0x40];
+
+ if (init() < 0)
+ exit(1);
+
+ /* we've established T=CL at this point */
+
+ rfid_reader_close(rh);
+
+ exit(0);
+}
diff --git a/rc632.h b/rc632.h
new file mode 100644
index 0000000..41beb2a
--- /dev/null
+++ b/rc632.h
@@ -0,0 +1,209 @@
+/* Register definitions for Philips CL RC632 RFID Reader IC
+ *
+ * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ *
+ * Licensed under GNU General Public License, Version 2
+ */
+
+enum rc632_registers {
+ RC632_REG_PAGE0 = 0x00,
+ RC632_REG_COMMAND = 0x01,
+ RC632_REG_FIFO_DATA = 0x02,
+ RC632_REG_PRIMARY_STATUS = 0x03,
+ RC632_REG_FIFO_LENGTH = 0x04,
+ RC632_REG_SECONDARY_STATUS = 0x05,
+ RC632_REG_INTERRUPT_EN = 0x06,
+ RC632_REG_INTERRUPT_RQ = 0x07,
+
+ RC632_REG_PAGE1 = 0x08,
+ RC632_REG_CONTROL = 0x09,
+ RC632_REG_ERROR_FLAG = 0x0a,
+ RC632_REG_COLL_POS = 0x0b,
+ RC632_REG_TIMER_VALUE = 0x0c,
+ RC632_REG_CRC_RESULT_LSB = 0x0d,
+ RC632_REG_CRC_RESULT_MSB = 0x0e,
+ RC632_REG_BIT_FRAMING = 0x0f,
+
+ RC632_REG_PAGE2 = 0x10,
+ RC632_REG_TX_CONTROL = 0x11,
+ RC632_REG_CW_CONDUCTANCE = 0x12,
+ RC632_REG_MOD_CONDUCTANCE = 0x13,
+ RC632_REG_CODER_CONTROL = 0x14,
+ RC632_REG_MOD_WIDTH = 0x15,
+ RC632_REG_MOD_WIDTH_SOF = 0x16,
+ RC632_REG_TYPE_B_FRAMING = 0x17,
+
+ RC632_REG_PAGE3 = 0x18,
+ RC632_REG_RX_CONTROL1 = 0x19,
+ RC632_REG_DECODER_CONTROL = 0x1a,
+ RC632_REG_BIT_PHASE = 0x1b,
+ RC632_REG_RX_THRESHOLD = 0x1c,
+ RC632_REG_BPSK_DEM_CONTROL = 0x1d,
+ RC632_REG_RX_CONTROL2 = 0x1e,
+ RC632_REG_CLOCK_Q_CONTROL = 0x1f,
+
+ RC632_REG_PAGE4 = 0x20,
+ RC632_REG_RX_WAIT = 0x21,
+ RC632_REG_CHANNEL_REDUNDANCY = 0x22,
+ RC632_REG_CRC_PRESET_LSB = 0x23,
+ RC632_REG_CRC_PRESET_MSB = 0x24,
+ RC632_REG_TIME_SLOT_PERIOD = 0x25,
+ RC632_REG_MFOUT_SELECT = 0x26,
+ RC632_REG_PRESET_27 = 0x27,
+
+ RC632_REG_PAGE5 = 0x28,
+ RC632_REG_FIFO_LEVEL = 0x29,
+ RC632_REG_TIMER_CLOCK = 0x2a,
+ RC632_REG_TIMER_CONTROL = 0x2b,
+ RC632_REG_TIMER_RELOAD = 0x2c,
+ RC632_REG_IRQ_PIN_CONFIG = 0x2d,
+ RC632_REG_PRESET_2E = 0x2e,
+ RC632_REG_PRESET_2F = 0x2f,
+
+ RC632_REG_PAGE6 = 0x30,
+
+ RC632_REG_PAGE7 = 0x38,
+ RC632_REG_TEST_ANA_SELECT = 0x3a,
+ RC632_REG_TEST_DIGI_SELECT = 0x3d,
+};
+
+enum rc632_reg_command {
+ RC632_CMD_IDLE = 0x00,
+ RC632_CMD_WRITE_E2 = 0x01,
+ RC632_CMD_READ_E2 = 0x03,
+ RC632_CMD_LOAD_CONFIG = 0x07,
+ RC632_CMD_LOAD_KEY_E2 = 0x0b,
+ RC632_CMD_AUTHENT1 = 0x0c,
+ RC632_CMD_CALC_CRC = 0x12,
+ RC632_CMD_AUTHENT2 = 0x14,
+ RC632_CMD_RECEIVE = 0x16,
+ RC632_CMD_LOAD_KEY = 0x19,
+ RC632_CMD_TRANSMIT = 0x1a,
+ RC632_CMD_TRANSCIEVE = 0x1e,
+ RC632_CMD_STARTUP = 0x3f,
+};
+
+enum rc632_reg_control {
+ RC632_CONTROL_CRYPTO1_ON = 0x08,
+ RC632_CONTROL_POWERDOWN = 0x10,
+};
+
+enum rc632_reg_error_flag {
+ RC632_ERR_FLAG_COL_ERR = 0x01,
+ RC632_ERR_FLAG_PARITY_ERR = 0x02,
+ RC632_ERR_FLAG_FRAMING_ERR = 0x04,
+ RC632_ERR_FLAG_CRC_ERR = 0x08,
+ RC632_ERR_FLAG_FIFO_OVERFLOW = 0x10,
+ RC632_ERR_FLAG_ACCESS_ERR = 0x20,
+ RC632_ERR_FLAG_KEY_ERR = 0x40,
+};
+
+enum rc632_reg_tx_control {
+ RC632_TXCTRL_TX1_RF_EN = 0x01,
+ RC632_TXCTRL_TX2_RF_EN = 0x02,
+ RC632_TXCTRL_TX2_CW = 0x04,
+ RC632_TXCTRL_TX2_INV = 0x08,
+ RC632_TXCTRL_FORCE_100_ASK = 0x10,
+
+ RC632_TXCTRL_MOD_SRC_LOW = 0x00,
+ RC632_TXCTRL_MOD_SRC_HIGH = 0x20,
+ RC632_TXCTRL_MOD_SRC_INT = 0x40,
+ RC632_TXCTRL_MOD_SRC_MFIN = 0x60,
+};
+
+enum rc632_reg_coder_control {
+ RC632_CDRCTRL_TXCD_NRZ = 0x00,
+ RC632_CDRCTRL_TXCD_14443A = 0x01,
+ RC632_CDRCTRL_TXCD_ICODE_STD = 0x04,
+
+ RC632_CDRCTRL_RATE_848K = 0x00,
+ RC632_CDRCTRL_RATE_424K = 0x80,
+ RC632_CDRCTRL_RATE_212K = 0x10,
+ RC632_CDRCTRL_RATE_106K = 0x18,
+ RC632_CDRCTRL_RATE_14443B = 0x20,
+ RC632_CDRCTRL_RATE_15693 = 0x28,
+ RC632_CDRCTRL_RATE_ICODE_FAST = 0x30,
+};
+
+enum rc632_erg_type_b_framing {
+ RC632_TBFRAMING_SOF_10L_2H = 0x00,
+ RC632_TBFRAMING_SOF_10L_3H = 0x01,
+ RC632_TBFRAMING_SOF_11L_2H = 0x02,
+ RC632_TBFRAMING_SOF_11L_3H = 0x03,
+
+ RC632_TBFRAMING_EOF_10 = 0x00,
+ RC632_TBFRAMING_EOF_11 = 0x20,
+
+ RC632_TBFRAMING_NO_TX_SOF = 0x80,
+ RC632_TBFRAMING_NO_TX_EOF = 0x40,
+};
+#define RC632_TBFRAMING_SPACE_SHIFT 2
+#define RC632_TBFRAMING_SPACE_MASK 7
+
+enum rc632_reg_rx_control1 {
+ RC632_RXCTRL1_GAIN_20DB = 0x00,
+ RC632_RXCTRL1_GAIN_24DB = 0x01,
+ RC632_RXCTRL1_GAIN_31DB = 0x02,
+ RC632_RXCTRL1_GAIN_35DB = 0x03,
+
+ RC632_RXCTRL1_LP_OFF = 0x04,
+ RC632_RXCTRL1_ISO15693 = 0x08,
+ RC632_RXCTRL1_ISO14443 = 0x10,
+
+ RC632_RXCTRL1_SUBCP_1 = 0x00,
+ RC632_RXCTRL1_SUBCP_2 = 0x20,
+ RC632_RXCTRL1_SUBCP_4 = 0x40,
+ RC632_RXCTRL1_SUBCP_8 = 0x60,
+ RC632_RXCTRL1_SUBCP_16 = 0x80,
+};
+
+enum rc632_reg_decoder_control {
+ RC632_DECCTRL_MANCHESTER = 0x00,
+ RC632_DECCTRL_BPSK = 0x01,
+
+ RC632_DECCTRL_RX_INVERT = 0x04,
+
+ RC632_DECCTRL_RXFR_ICODE = 0x00,
+ RC632_DECCTRL_RXFR_14443A = 0x08,
+ RC632_DECCTRL_RXFR_15693 = 0x10,
+ RC632_DECCTRL_RXFR_14443B = 0x18,
+
+ RC632_DECCTRL_ZEROAFTERCOL = 0x20,
+
+ RC632_DECCTRL_RX_MULTIPLE = 0x40,
+};
+
+enum rc632_reg_bpsk_dem_control {
+ RC632_BPSKD_TAUB_SHIFT = 0x00,
+ RC632_BPSKD_TAUB_MASK = 0x03,
+
+ RC632_BPSKD_TAUD_SHIFT = 0x02,
+ RC632_BPSKD_TAUD_MASK = 0x03,
+
+ RC632_BPSKD_FILTER_AMP_DETECT = 0x10,
+ RC632_BPSKD_NO_RX_EOF = 0x20,
+ RC632_BPSKD_NO_RX_EGT = 0x40,
+ RC632_BPSKD_NO_RX_SOF = 0x80,
+};
+
+enum rc632_reg_rx_control2 {
+ RC632_RXCTRL2_DECSRC_LOW = 0x00,
+ RC632_RXCTRL2_DECSRC_INT = 0x01,
+ RC632_RXCTRL2_DECSRC_SUBC_MFIN = 0x10,
+ RC632_RXCTRL2_DECSRC_BASE_MFIN = 0x11,
+
+ RC632_RXCTRL2_AUTO_PD = 0x40,
+ RC632_RXCTRL2_CLK_I = 0x80,
+ RC632_RXCTRL2_CLK_Q = 0x00,
+};
+
+enum rc632_reg_channel_redundancy {
+ RC632_CR_PARITY_ENABLE = 0x01,
+ RC632_CR_PARITY_ODD = 0x02,
+ RC632_CR_TX_CRC_ENABLE = 0x04,
+ RC632_CR_RX_CRC_ENABLE = 0x08,
+ RC632_CR_CRC8 = 0x10,
+ RC632_CR_CRC3309 = 0x20,
+};
+
+
diff --git a/rfid.c b/rfid.c
new file mode 100644
index 0000000..3c375b2
--- /dev/null
+++ b/rfid.c
@@ -0,0 +1,39 @@
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rfid/rfid_reader_cm5121.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_protocol_tcl.h>
+
+const char *
+rfid_hexdump(const void *data, unsigned int len)
+{
+ static char string[1024];
+ unsigned char *d = (unsigned char *) data;
+ unsigned int i, left;
+
+ string[0] = '\0';
+ left = sizeof(string);
+ for (i = 0; len--; i += 3) {
+ if (i >= sizeof(string) -4)
+ break;
+ snprintf(string+i, 4, " %02x", *d++);
+ }
+ return string;
+}
+
+int rfid_init()
+{
+ rfid_reader_register(&rfid_reader_cm5121);
+ rfid_layer2_register(&rfid_layer2_iso14443a);
+ rfid_layer2_register(&rfid_layer2_iso14443b);
+ rfid_protocol_register(&rfid_protocol_tcl);
+
+ return 0;
+}
+
+void rfid_fini()
+{
+ /* FIXME: implementation */
+}
diff --git a/rfid_asic_rc632.c b/rfid_asic_rc632.c
new file mode 100644
index 0000000..3d5b621
--- /dev/null
+++ b/rfid_asic_rc632.c
@@ -0,0 +1,833 @@
+/* Generic Philips CL RC632 Routines
+ *
+ * (C) Harald Welte <laforge@gnumonks.org>
+ *
+ * Licensed under GNU General Public License, Version 2
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_reader_cm5121.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+#include "rfid_iso14443_common.h"
+#include "rc632.h"
+//#include "rc632_14443a.h"
+
+
+#define ENTER() DEBUGP("entering\n")
+struct rfid_asic rc632;
+
+/* Register and FIFO Access functions */
+int
+rc632_reg_write(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char val)
+{
+ return handle->rath->rat->priv.rc632.fn.reg_write(handle->rath, reg, val);
+}
+
+int
+rc632_reg_read(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char *val)
+{
+ return handle->rath->rat->priv.rc632.fn.reg_read(handle->rath, reg, val);
+}
+
+int
+rc632_fifo_write(struct rfid_asic_handle *handle,
+ unsigned char len,
+ const unsigned char *buf,
+ unsigned char flags)
+{
+ return handle->rath->rat->priv.rc632.fn.fifo_write(handle->rath,
+ len, buf, flags);
+}
+
+int
+rc632_fifo_read(struct rfid_asic_handle *handle,
+ unsigned char len,
+ unsigned char *buf)
+{
+ return handle->rath->rat->priv.rc632.fn.fifo_read(handle->rath, len, buf);
+}
+
+
+int
+rc632_set_bits(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char val)
+{
+ int ret;
+ unsigned char tmp;
+
+ ret = rc632_reg_read(handle, reg, &tmp);
+ if (ret < 0)
+ return -1;
+
+ /* if bits are already set, no need to set them again */
+ if ((tmp & val) == val)
+ return 0;
+
+ return rc632_reg_write(handle, reg, (tmp|val)&0xff);
+}
+
+int
+rc632_clear_bits(struct rfid_asic_handle *handle,
+ unsigned char reg,
+ unsigned char val)
+{
+ int ret;
+ unsigned char tmp;
+
+ ret = rc632_reg_read(handle, reg, &tmp);
+ if (ret < 0) {
+ DEBUGP("error during reg_read(%p, %d):%d\n",
+ handle, reg, ret);
+ return -1;
+ }
+ /* if bits are already cleared, no need to clear them again */
+ if ((tmp & val) == 0)
+ return 0;
+
+ return rc632_reg_write(handle, reg, (tmp & ~val)&0xff);
+}
+
+
+
+int
+rc632_turn_on_rf(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03);
+}
+
+int
+rc632_turn_off_rf(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03);
+}
+
+int
+rc632_power_up(struct rfid_asic_handle *handle)
+{
+ ENTER();
+ return rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_POWERDOWN);
+}
+
+int
+rc632_power_down(struct rfid_asic_handle *handle)
+{
+ return rc632_set_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_POWERDOWN);
+}
+
+/* Stupid RC623 implementations don't evaluate interrupts but poll the
+ * command register for "status idle" */
+int
+rc632_wait_idle(struct rfid_asic_handle *handle, unsigned int time)
+{
+ unsigned char cmd = 0xff;
+ int ret;
+
+ while (cmd != 0) {
+ ret = rc632_reg_read(handle, RC632_REG_COMMAND, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (cmd == 0) {
+ /* FIXME: read second time ?? */
+ return 0;
+ }
+
+ {
+ unsigned char foo;
+ rc632_reg_read(handle, RC632_REG_PRIMARY_STATUS, &foo);
+ if (foo & 0x04)
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &foo);
+ }
+
+ usleep(100);
+
+ /* Fixme: Abort after some timeout */
+ }
+
+ return 0;
+}
+
+int
+rc632_transmit(struct rfid_asic_handle *handle,
+ const unsigned char *buf,
+ unsigned char len,
+ unsigned int timeout)
+{
+ int ret;
+
+ ret = rc632_fifo_write(handle, len, buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSMIT);
+ if (ret < 0)
+ return ret;
+
+ return rc632_wait_idle(handle, timeout);
+}
+
+static int
+tcl_toggle_pcb(struct rfid_asic_handle *handle)
+{
+ // FIXME: toggle something between 0x0a and 0x0b
+ return 0;
+}
+
+int
+rc632_transcieve(struct rfid_asic_handle *handle,
+ const unsigned char *tx_buf,
+ unsigned char tx_len,
+ unsigned char *rx_buf,
+ unsigned char *rx_len,
+ unsigned int timer,
+ unsigned int toggle)
+{
+ int ret;
+
+ ret = rc632_fifo_write(handle, tx_len, tx_buf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_TRANSCIEVE);
+ if (ret < 0)
+ return ret;
+
+ if (toggle == 1)
+ tcl_toggle_pcb(handle);
+
+ ret = rc632_wait_idle(handle, timer);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(handle, RC632_REG_FIFO_LENGTH, rx_len);
+ if (ret < 0)
+ return ret;
+
+ if (*rx_len == 0) {
+ unsigned char tmp;
+
+ DEBUGP("rx_len == 0\n");
+
+ rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &tmp);
+ rc632_reg_read(handle, RC632_REG_CHANNEL_REDUNDANCY, &tmp);
+
+ return -1;
+ }
+
+ return rc632_fifo_read(handle, *rx_len, rx_buf);
+}
+
+int
+rc632_read_eeprom(struct rfid_asic_handle *handle)
+{
+ unsigned char recvbuf[60];
+ unsigned char sndbuf[3];
+ int ret;
+
+ sndbuf[0] = 0x00;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x3c;
+
+ ret = rc632_fifo_write(handle, 3, sndbuf, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_READ_E2);
+ if (ret < 0)
+ return ret;
+
+ usleep(20000);
+
+ ret = rc632_fifo_read(handle, sizeof(recvbuf), recvbuf);
+ if (ret < 0)
+ return ret;
+
+ // FIXME: do something with eeprom contents
+ return ret;
+}
+
+int
+rc632_calc_crc16_from(struct rfid_asic_handle *handle)
+{
+ unsigned char sndbuf[2] = { 0x01, 0x02 };
+ unsigned char crc_lsb = 0x00 , crc_msb = 0x00;
+ int ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x12);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xe0);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_fifo_write(handle, sizeof(sndbuf), sndbuf, 3);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_COMMAND, RC632_CMD_CALC_CRC);
+ if (ret < 0)
+ return ret;
+
+ usleep(10000); // FIXME: no checking for cmd completion?
+
+ ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_LSB, &crc_lsb);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_read(handle, RC632_REG_CRC_RESULT_MSB, &crc_msb);
+ if (ret < 0)
+ return ret;
+
+ // FIXME: what to do with crc result?
+ return ret;
+}
+
+
+int
+rc632_register_dump(struct rfid_asic_handle *handle, unsigned char *buf)
+{
+ int ret;
+ unsigned char i;
+
+ for (i = 0; i <= 0x3f; i++) {
+ ret = rc632_reg_read(handle, i, &buf[i]);
+ // do we want error checks?
+ }
+ return 0;
+}
+
+
+
+/* generic FIFO access functions (if no more efficient ones provided by
+ * transport driver) */
+
+static int
+generic_fifo_write()
+{
+ // FIXME: implementation (not needed for CM 5121)
+ return -1;
+}
+
+static int
+generic_fifo_read()
+{
+ // FIXME: implementation (not neded for CM 5121)
+ return -1;
+}
+
+static int
+rc632_init(struct rfid_asic_handle *ah)
+{
+ int ret;
+
+ /* switch on rf */
+ ret = rc632_power_up(ah);
+ if (ret < 0)
+ return ret;
+
+ /* disable register paging */
+ ret = rc632_reg_write(ah, 0x00, 0x00);
+ if (ret < 0)
+ return ret;
+
+ /* set some sane default values */
+ ret = rc632_reg_write(ah, 0x11, 0x5b);
+ if (ret < 0)
+ return ret;
+
+ /* switch on rf */
+ ret = rc632_turn_on_rf(ah);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_fini(struct rfid_asic_handle *ah)
+{
+ int ret;
+
+ /* switch off rf */
+ ret = rc632_turn_off_rf(ah);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_power_down(ah);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+struct rfid_asic_handle *
+rc632_open(struct rfid_asic_transport_handle *th)
+{
+ struct rfid_asic_handle *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+ memset(h, 0, sizeof(*h));
+
+ h->asic = &rc632;
+ h->rath = th;
+ h->fc = h->asic->fc;
+ h->mtu = h->mru = 40; /* FIXME */
+
+ if (rc632_init(h) < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+void
+rc632_close(struct rfid_asic_handle *h)
+{
+ rc632_fini(h);
+ free(h);
+}
+
+
+/*
+ * Philips CL RC632 primitives for ISO 14443-A compliant PICC's
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+static int
+rc632_iso14443a_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+ // FIXME: some fifo work (drain fifo?)
+
+ /* flush fifo (our way) */
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_FORCE_100_ASK |
+ RC632_TXCTRL_MOD_SRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE,
+ CM5121_CW_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE,
+ CM5121_MOD_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_TXCD_14443A |
+ RC632_CDRCTRL_RATE_106K));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_MANCHESTER |
+ RC632_DECCTRL_RXFR_14443A));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ CM5121_14443A_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_14443A_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_DECSRC_INT |
+ RC632_RXCTRL2_CLK_Q));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso14443a_fini(struct iso14443a_handle *handle_14443)
+{
+
+#if 0
+ ret = rc632_turn_off_rf(handle);
+ if (ret < 0)
+ return ret;
+#endif
+
+
+ return 0;
+}
+
+
+/* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */
+static int
+rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ int ret;
+ unsigned char tx_buf[1];
+ unsigned char rx_len = 2;
+
+ memset(atqa, 0, sizeof(atqa));
+
+ tx_buf[0] = cmd;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+
+#endif
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf),
+ (unsigned char *)atqa, &rx_len, 0x32, 0);
+ if (ret < 0) {
+ DEBUGP("error during rc632_transcieve()\n");
+ return ret;
+ }
+
+ /* switch back to normal 8bit last byte */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if (rx_len != 2) {
+ DEBUGP("rx_len(%d) != 2\n", rx_len);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* trasncieve regular frame */
+static int
+rc632_iso14443a_transcieve(struct rfid_asic_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ int ret;
+ unsigned char rxl = *rx_len & 0xff;
+
+ memset(rx_buf, 0, *rx_len);
+
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD |
+ RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE));
+#endif
+ ret = rc632_set_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+/* transcieve anti collission bitframe */
+static int
+rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ int ret;
+ unsigned char rx_buf[64];
+ unsigned char rx_len = sizeof(rx_buf);
+ unsigned char rx_align = 0, tx_last_bits, tx_bytes;
+ unsigned char boc;
+ unsigned char error_flag;
+ *bit_of_col = ISO14443A_BITOFCOL_NONE;
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ /* disable CRC summing */
+#if 0
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+#else
+ ret = rc632_clear_bits(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE|RC632_CR_TX_CRC_ENABLE);
+#endif
+ if (ret < 0)
+ return ret;
+
+ tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */
+ tx_bytes = acf->nvb >> 4;
+ if (tx_last_bits) {
+ tx_bytes++;
+ rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */
+ }
+
+ //rx_align = 8 - tx_last_bits;/* rx frame complements tx */
+
+ /* set RxAlign and TxLastBits*/
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING,
+ (rx_align << 4) | (tx_last_bits));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, (unsigned char *)acf, tx_bytes,
+ rx_buf, &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* bitwise-OR the two halves of the split byte */
+ acf->uid_bits[tx_bytes-2] = (
+ (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits)))
+ | rx_buf[0]);
+ /* copy the rest */
+ memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1);
+
+ /* determine whether there was a collission */
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag);
+ if (ret < 0)
+ return ret;
+
+ if (error_flag & RC632_ERR_FLAG_COL_ERR) {
+ /* retrieve bit of collission */
+ ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc);
+ if (ret < 0)
+ return ret;
+
+ /* bit of collission relative to start of part 1 of
+ * anticollision frame (!) */
+ *bit_of_col = 2*8 + boc;
+ }
+
+ return 0;
+}
+
+static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+ // FIXME: some FIFO work
+
+ /* flush fifo (our way) */
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_MOD_SRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_TXCD_NRZ |
+ RC632_CDRCTRL_RATE_14443B));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING,
+ (RC632_TBFRAMING_SOF_11L_3H |
+ (6 << RC632_TBFRAMING_SPACE_SHIFT) |
+ RC632_TBFRAMING_EOF_11));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_BPSK |
+ RC632_DECCTRL_RXFR_14443B));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ CM5121_14443B_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_14443B_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL,
+ ((0x2 & RC632_BPSKD_TAUB_MASK)<<RC632_BPSKD_TAUB_SHIFT |
+ (0x3 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT |
+ RC632_BPSKD_FILTER_AMP_DETECT |
+ RC632_BPSKD_NO_RX_EOF |
+ RC632_BPSKD_NO_RX_EGT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_AUTO_PD |
+ RC632_RXCTRL2_DECSRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_CRC3309));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+struct rfid_asic rc632 = {
+ .name = "Philips CL RC632",
+ .fc = ISO14443_FREQ_CARRIER,
+ .priv.rc632 = {
+ .fn.power_up = &rc632_power_up,
+ .fn.power_down = &rc632_power_down,
+ .fn.turn_on_rf = &rc632_turn_on_rf,
+ .fn.turn_off_rf = &rc632_turn_off_rf,
+ .fn.transcieve = &rc632_iso14443a_transcieve,
+ .fn.iso14443a = {
+ .init = &rc632_iso14443a_init,
+ .transcieve_sf = &rc632_iso14443a_transcieve_sf,
+ .transcieve_acf = &rc632_iso14443a_transcieve_acf,
+ },
+ .fn.iso14443b = {
+ .init = &rc632_iso14443b_init,
+ },
+ },
+};
+
+
diff --git a/rfid_asic_rc632_14443a.c b/rfid_asic_rc632_14443a.c
new file mode 100644
index 0000000..d6c0358
--- /dev/null
+++ b/rfid_asic_rc632_14443a.c
@@ -0,0 +1,393 @@
+/*
+ * Philips CL RC632 primitives for ISO 14443-A compliant PICC's
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+#include "rc632.h"
+
+#include "cm5121_rfid.h" /* FIXME: this needs to be modular */
+
+static int
+rc632_iso14443a_init(struct rfid_asic_handle *handle)
+{
+ int ret;
+
+#if 0
+ ret = rc632_power_up(handle);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_turn_on_rf(handle);
+ if (ret < 0)
+ return ret;
+#endif
+
+ // FIXME: some fifo work (drain fifo?)
+
+ /* flush fifo (our way) */
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_FORCE_100_ASK |
+ RC632_TXCTRL_MOD_SRC_INT));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE,
+ CM5121_CW_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE,
+ CM5121_MOD_CONDUCTANCE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CODER_CONTROL,
+ (RC632_CDRCTRL_TXCD_14443A |
+ RC632_CDRCTRL_RATE_106K));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH_SOF, 0x3f);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODER_CONTROL,
+ (RC632_DECCTRL_MANCHESTER |
+ RC632_DECCTRL_RXFR_14443A));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ CM5121_14443A_BITPHASE);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_14443A_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_DECSRC_INT |
+ RC632_RXCTRL2_CLK_Q));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0x63);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+rc632_iso14443a_fini(struct iso14443a_handle *handle_14443)
+{
+
+#if 0
+ ret = rc632_turn_off_rf(handle);
+ if (ret < 0)
+ return ret;
+#endif
+
+
+ return 0;
+}
+
+#if 0
+int
+rc632_iso14443a_select(struct rc632_handle *handle,
+ unsigned char *retptr,
+ )
+{
+ int ret;
+ unsigned char tx_buf[7];
+ unsigned char rx_buf[64];
+ unsigned char rx_len = 1;
+
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ tx_buf[0] = arg_8;
+ tx_buf[1] = 0x70;
+ (u_int32_t *)tx_buf[2] = arg_4;
+ tx_buf[6] = arg4+4;
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bit(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD |
+ RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 0x32, 0);
+
+ if (ret < 0 || rx_len != 1)
+ return ret;
+
+ *retptr = rx_buf[0];
+
+ return 0;
+}
+
+/* issue a 14443-3 A PCD -> PICC command, such as REQA, WUPA */
+int
+rc632_iso14443a_req(sutruct rc632_handle *handle, unsigned char req,
+ unsigned char *resp)
+{
+ int ret;
+ unsigned char tx_buf[1];
+ unsigned char rx_buf[0x40];
+ unsigned char rx_len = 2;
+
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ tx_buf[0] = req;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf), rx_buf,
+ &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* switch back to normal 8bit last byte */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if ((rx_len != 2) || (rx_buf[1] != 0xf0))
+ return -1;
+
+ resp[0] = rx_buf[0];
+ resp[1] = rx_buf[1];
+
+ return 0;
+}
+#endif
+
+/* issue a 14443-3 A PCD -> PICC command in a short frame, such as REQA, WUPA */
+static int
+rc632_iso14443a_transcieve_sf(struct rfid_asic_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ int ret;
+ unsigned char tx_buf[1];
+ unsigned char rx_len = 2;
+
+ memset(atqa, 0, sizeof(atqa));
+
+ tx_buf[0] = cmd;
+
+ /* transfer only 7 bits of last byte in frame */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x07);
+ if (ret < 0)
+ return ret;
+
+
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, sizeof(tx_buf),
+ (unsigned char *)atqa, &rx_len, 0x32, 0);
+ if (ret < 0) {
+ DEBUGP("error during rc632_transcieve()\n");
+ return ret;
+ }
+
+ /* switch back to normal 8bit last byte */
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if (rx_len != 2) {
+ DEBUGP("rx_len(%d) != 2\n", rx_len);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* trasncieve regular frame */
+static int
+rc632_iso14443a_transcieve(struct rfid_asic_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ int ret;
+ unsigned char rxl = *rx_len & 0xff;
+
+ memset(rx_buf, 0, *rx_len);
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD |
+ RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, tx_buf, tx_len, rx_buf, &rxl, 0x32, 0);
+ *rx_len = rxl;
+ if (ret < 0)
+ return ret;
+
+
+ return 0;
+}
+
+/* transcieve anti collission bitframe */
+static int
+rc632_iso14443a_transcieve_acf(struct rfid_asic_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ int ret;
+ unsigned char rx_buf[64];
+ unsigned char rx_len = sizeof(rx_buf);
+ unsigned char rx_align = 0, tx_last_bits, tx_bytes;
+ unsigned char boc;
+ unsigned char error_flag;
+ *bit_of_col = ISO14443A_BITOFCOL_NONE;
+ memset(rx_buf, 0, sizeof(rx_buf));
+
+ /* disable mifare cryto */
+ ret = rc632_clear_bits(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_CRYPTO1_ON);
+ if (ret < 0)
+ return ret;
+
+ /* disalbe CRC summing */
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_REDUNDANCY,
+ (RC632_CR_PARITY_ENABLE |
+ RC632_CR_PARITY_ODD));
+ if (ret < 0)
+ return ret;
+
+ tx_last_bits = acf->nvb & 0x0f; /* lower nibble indicates bits */
+ tx_bytes = acf->nvb >> 4;
+ if (tx_last_bits) {
+ tx_bytes++;
+ rx_align = (tx_last_bits+1) % 8;/* rx frame complements tx */
+ }
+
+ //rx_align = 8 - tx_last_bits;/* rx frame complements tx */
+
+ /* set RxAlign and TxLastBits*/
+ ret = rc632_reg_write(handle, RC632_REG_BIT_FRAMING,
+ (rx_align << 4) | (tx_last_bits));
+ if (ret < 0)
+ return ret;
+
+ ret = rc632_transcieve(handle, (unsigned char *)acf, tx_bytes,
+ rx_buf, &rx_len, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ /* bitwise-OR the two halves of the split byte */
+ acf->uid_bits[tx_bytes-2] = (
+ (acf->uid_bits[tx_bytes-2] & (0xff >> (8-tx_last_bits)))
+ | rx_buf[0]);
+ /* copy the rest */
+ memcpy(&acf->uid_bits[tx_bytes+1-2], &rx_buf[1], rx_len-1);
+
+ /* determine whether there was a collission */
+ ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag);
+ if (ret < 0)
+ return ret;
+
+ if (error_flag & RC632_ERR_FLAG_COL_ERR) {
+ /* retrieve bit of collission */
+ ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc);
+ if (ret < 0)
+ return ret;
+
+ /* bit of collission relative to start of part 1 of
+ * anticollision frame (!) */
+ *bit_of_col = 2*8 + boc;
+ }
+
+ return 0;
+}
+
+
diff --git a/rfid_asic_rc632_14443b.c b/rfid_asic_rc632_14443b.c
new file mode 100644
index 0000000..62aa224
--- /dev/null
+++ b/rfid_asic_rc632_14443b.c
@@ -0,0 +1,69 @@
+
+#include "rc632.h"
+
+int rc632_iso14443b_init(struct rc632_handle *handle)
+{
+ // FIXME: some FIFO work
+ //
+ ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
+ (RC632_TXCTRL_TX1_RF_EN |
+ RC632_TXCTRL_TX2_RF_EN |
+ RC632_TXCTRL_TX2_INV |
+ RC632_TXCTRL_MOD_SRC_INT));
+
+ ret = rc632_reg_write(handle, RC632_REG_CW_CONDUCTANCE, 0x3f);
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_CONDUCTANCE, 0x04);
+
+ ret = rc632_reg_write(handle, RC632_REG_CODE_CONTROL,
+ (RC632_CDRCTRL_TXCD_NRZ |
+ RC632_CDRCTRL_RATE_14443B));
+
+ ret = rc632_reg_write(handle, RC632_REG_MOD_WIDTH, 0x13);
+
+ ret = rc632_reg_write(handle, RC632_REG_SOF_WIDTH, 0x3f);
+
+ ret = rc632_reg_write(handle, RC632_REG_TYPE_B_FRAMING,
+ (RC632_TBFRAMING_SOF_11L_3H |
+ (6 << RC632_TBFRAMING_SPACE_SHIFT) |
+ RC632_TBFRAMING_EOF_11));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL1,
+ (RC632_RXCTRL1_GAIN_35DB |
+ RC632_RXCTRL1_ISO14443 |
+ RC632_RXCTRL1_SUBCP_8));
+
+ ret = rc632_reg_write(handle, RC632_REG_DECODE_CONTROL,
+ (RC632_DECCTRL_BPSK |
+ RC632_DECCTRL_RXFR_14443B));
+
+ ret = rc632_reg_write(handle, RC632_REG_BIT_PHASE,
+ CM5121_14443B_BITPHASE);
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_THRESHOLD,
+ CM5121_14443B_THRESHOLD);
+
+ ret = rc632_reg_write(handle, RC632_REG_BPSK_DEM_CONTROL,
+ ((0x10 & RC632_BPSKD_TAUB_MASK)<<RC632_BPSKD_TAUB_SHIFT |
+ (0x11 & RC632_BPSKD_TAUD_MASK)<<RC632_BPSKD_TAUD_SHIFT |
+ RC632_BPSKD_FILTER_AMP_DETECT |
+ RC632_BPSKD_NO_RX_EOF |
+ RC632_BPSKD_NO_RX_EGT));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_CONTROL2,
+ (RC632_RXCTRL2_AUTO_PD |
+ RC632_RXCTRL2_DECSRC_INT));
+
+ ret = rc632_reg_write(handle, RC632_REG_RX_WAIT, 0x03);
+
+ ret = rc632_reg_write(handle, RC632_REG_CHANNEL_RDUNDANCY,
+ (RC632_CR_TX_CRC_ENABLE |
+ RC632_CR_RX_CRC_ENABLE |
+ RC632_CR_CR3309));
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_LSB, 0xff);
+
+ ret = rc632_reg_write(handle, RC632_REG_CRC_PRESET_MSB, 0xff);
+
+}
+
diff --git a/rfid_asic_rc632_mifare.c b/rfid_asic_rc632_mifare.c
new file mode 100644
index 0000000..9bfb0ae
--- /dev/null
+++ b/rfid_asic_rc632_mifare.c
@@ -0,0 +1,25 @@
+
+int
+rc632_mifare_read16()
+{
+ unsigned char sndbuf[2];
+ unsigned char recvbuf[0x40];
+ unsigned char recvlen = sizeof(recvbuf);
+
+ int ret;
+
+ sndbuf[0] = 0x30;
+ sndbuf[1] = arg_4;
+
+ memset(recvbuf, 0, sizeof(recvbuf));
+
+ ret = rc632_transcieve(handle, sndbuf, sizeof(sndbuf),
+ recvbuf, &recvlen, 0x32, 0);
+ if (ret < 0)
+ return ret;
+
+ if (recvlen != 0x10)
+ return -1;
+
+ return 0;
+}
diff --git a/rfid_iso14443_common.c b/rfid_iso14443_common.c
new file mode 100644
index 0000000..aacb45d
--- /dev/null
+++ b/rfid_iso14443_common.c
@@ -0,0 +1,41 @@
+static unsigned int fsdi_table[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
+
+int iso14443_fsdi_to_fsd(unsigned int *fsd, unsigned char fsdi)
+{
+ /* ISO 14443-4:2000(E) Section 5.1. */
+ if (fsdi > sizeof(fsdi_table)/sizeof(unsigned int))
+ return -1;
+
+ *fsd = fsdi_table[fsdi];
+ return 0;
+}
+
+int iso14443_fsd_to_fsdi(unsigned char *fsdi, unsigned int fsd)
+{
+ int i;
+
+ for (i = 0; i < sizeof(fsdi_table)/sizeof(unsigned int); i++) {
+ if (fsdi_table[i] == fsd) {
+ *fsdi = i;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* calculate the fsd that is equal or the closest smaller value
+ * that can be coded as fsd */
+unsigned int iso14443_fsd_approx(unsigned int fsd)
+{
+ unsigned int tbl_size = sizeof(fsdi_table)/sizeof(unsigned int);
+ int i;
+
+ for (i = tbl_size-1; i >= 0; i--) {
+ if (fsdi_table[i] <= fsd)
+ return fsdi_table[i];
+ }
+ /* not reached: return smallest possible FSD */
+ return fsdi_table[0];
+}
+
diff --git a/rfid_iso14443_common.h b/rfid_iso14443_common.h
new file mode 100644
index 0000000..848d983
--- /dev/null
+++ b/rfid_iso14443_common.h
@@ -0,0 +1,11 @@
+#ifndef __RFID_ISO14443_COMMON_H
+#define __RFID_ISO14443_COMMON_H
+
+int iso14443_fsdi_to_fsd(unsigned int *fsd, unsigned char fsdi);
+int iso14443_fsd_to_fsdi(unsigned char *fsdi, unsigned int fsd);
+unsigned int iso14443_fsd_approx(unsigned int fsd);
+
+#define ISO14443_FREQ_CARRIER 13560000
+#define ISO14443_FREQ_SUBCARRIER (ISO14443_FREQ_CARRIER/16)
+
+#endif
diff --git a/rfid_layer2.c b/rfid_layer2.c
new file mode 100644
index 0000000..eb7cb2d
--- /dev/null
+++ b/rfid_layer2.c
@@ -0,0 +1,59 @@
+/* librfid - layer 2 protocol handler
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+
+static struct rfid_layer2 *rfid_layer2_list;
+
+struct rfid_layer2_handle *
+rfid_layer2_init(struct rfid_reader_handle *rh, unsigned int id)
+{
+ struct rfid_layer2 *p;
+
+ for (p = rfid_layer2_list; p; p = p->next)
+ if (p->id == id)
+ return p->fn.init(rh);
+
+ DEBUGP("unable to find matching layer2 protocol\n");
+ return NULL;
+}
+
+int
+rfid_layer2_open(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.open(ph);
+}
+
+int
+rfid_layer2_transcieve(struct rfid_layer2_handle *ph,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return ph->l2->fn.transcieve(ph, tx_buf, len, rx_buf, rx_len,
+ timeout, flags);
+}
+
+int rfid_layer2_fini(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.fini(ph);
+}
+
+int
+rfid_layer2_close(struct rfid_layer2_handle *ph)
+{
+ return ph->l2->fn.close(ph);
+}
+
+int
+rfid_layer2_register(struct rfid_layer2 *p)
+{
+ p->next = rfid_layer2_list;
+ rfid_layer2_list = p;
+
+ return 0;
+}
diff --git a/rfid_layer2_iso14443a.c b/rfid_layer2_iso14443a.c
new file mode 100644
index 0000000..fbad9d8
--- /dev/null
+++ b/rfid_layer2_iso14443a.c
@@ -0,0 +1,277 @@
+/* ISO 14443-3 A anticollision implementation
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2_iso14443a.h>
+
+#define TIMEOUT 1236
+
+/* Transcieve a 7-bit short frame */
+static int
+iso14443a_transcieve_sf(struct rfid_layer2_handle *handle,
+ unsigned char cmd,
+ struct iso14443a_atqa *atqa)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_sf(handle->rh, cmd, atqa);
+}
+
+/* Transmit an anticollission bit frame */
+static int
+iso14443a_transcieve_acf(struct rfid_layer2_handle *handle,
+ struct iso14443a_anticol_cmd *acf,
+ unsigned int *bit_of_col)
+{
+ struct rfid_reader *rdr = handle->rh->reader;
+
+ return rdr->iso14443a.transcieve_acf(handle->rh, acf, bit_of_col);
+}
+
+/* Transmit a regular frame */
+static int
+iso14443a_transcieve(struct rfid_layer2_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return handle->rh->reader->transcieve(handle->rh, tx_buf, tx_len,
+ rx_buf, rx_len, timeout, flags);
+}
+
+static int
+iso14443a_code_nvb_bits(unsigned char *nvb, unsigned int bits)
+{
+ unsigned int byte_count = bits / 8;
+ unsigned int bit_count = bits % 8;
+
+ if (byte_count < 2 || byte_count > 7)
+ return -1;
+
+ *nvb = ((byte_count & 0xf) << 4) | bit_count;
+
+ return 0;
+}
+
+/* first bit is '1', second bit '2' */
+static void
+set_bit_in_field(unsigned char *bitfield, unsigned int bit)
+{
+ unsigned int byte_count = bit / 8;
+ unsigned int bit_count = bit % 8;
+
+ DEBUGP("bitfield=%p, byte_count=%u, bit_count=%u\n",
+ bitfield, byte_count, bit_count);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+ *(bitfield+byte_count) |= 1 << (bit_count-1);
+ DEBUGP("%p = 0x%02x\n", (bitfield+byte_count), *(bitfield+byte_count));
+}
+
+static int
+iso14443a_anticol(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned int uid_size;
+ struct iso14443a_atqa atqa;
+ struct iso14443a_anticol_cmd acf;
+ unsigned int bit_of_col;
+ unsigned char sak[3];
+ unsigned char uid[10]; // triple size equals 10 bytes;
+ unsigned int rx_len = sizeof(sak);
+ char *aqptr = (char *) &atqa;
+
+ memset(uid, 0, sizeof(uid));
+ memset(sak, 0, sizeof(sak));
+ memset(&atqa, 0, sizeof(atqa));
+ memset(&acf, 0, sizeof(acf));
+
+ ret = iso14443a_transcieve_sf(handle, ISO14443A_SF_CMD_REQA, &atqa);
+ if (ret < 0) {
+ handle->priv.iso14443a.state = ISO14443A_STATE_REQA_SENT;
+ DEBUGP("error during transcieve_sf: %d\n", ret);
+ return ret;
+ }
+ handle->priv.iso14443a.state = ISO14443A_STATE_ATQA_RCVD;
+
+ DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1));
+
+ if (!atqa.bf_anticol) {
+ handle->priv.iso14443a.state =ISO14443A_STATE_NO_BITFRAME_ANTICOL;
+ DEBUGP("no bitframe anticollission bits set, aborting\n");
+ return -1;
+ }
+
+ if (atqa.uid_size == 2 || atqa.uid_size == 3)
+ uid_size = 3;
+ else if (atqa.uid_size == 1)
+ uid_size = 2;
+ else
+ uid_size = 1;
+
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL1;
+
+ handle->priv.iso14443a.state = ISO14443A_STATE_ANTICOL_RUNNING;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL1;
+
+cascade:
+ iso14443a_code_nvb_bits(&acf.nvb, 16);
+
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ if (ret < 0)
+ return ret;
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+
+ while (bit_of_col != ISO14443A_BITOFCOL_NONE) {
+ set_bit_in_field(&acf.uid_bits[0], bit_of_col-16);
+ iso14443a_code_nvb_bits(&acf.nvb, bit_of_col);
+ ret = iso14443a_transcieve_acf(handle, &acf, &bit_of_col);
+ DEBUGP("bit_of_col = %u\n", bit_of_col);
+ if (ret < 0)
+ return ret;
+ }
+
+ iso14443a_code_nvb_bits(&acf.nvb, 7*8);
+ ret = iso14443a_transcieve(handle, (unsigned char *)&acf, 7,
+ (unsigned char *) &sak, &rx_len,
+ TIMEOUT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (sak[0] & 0x04) {
+ /* Cascade bit set, UID not complete */
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* cascading from CL1 to CL2 */
+ if (acf.uid_bits[0] != 0x88) {
+ DEBUGP("Cascade bit set, but UID0 != 0x88\n");
+ return -1;
+ }
+ memcpy(&uid[0], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL2;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL2;
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* cascading from CL2 to CL3 */
+ memcpy(&uid[3], &acf.uid_bits[1], 3);
+ acf.sel_code = ISO14443A_AC_SEL_CODE_CL3;
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_CL3;
+ break;
+ default:
+ DEBUGP("cannot cascade any further than CL3\n");
+ handle->priv.iso14443a.state = ISO14443A_STATE_ERROR;
+ return -1;
+ break;
+ }
+ goto cascade;
+
+ } else {
+ switch (acf.sel_code) {
+ case ISO14443A_AC_SEL_CODE_CL1:
+ /* single size UID (4 bytes) */
+ memcpy(&uid[0], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL2:
+ /* double size UID (7 bytes) */
+ memcpy(&uid[3], &acf.uid_bits[0], 4);
+ break;
+ case ISO14443A_AC_SEL_CODE_CL3:
+ /* triple size UID (10 bytes) */
+ memcpy(&uid[6], &acf.uid_bits[0], 4);
+ break;
+ }
+ }
+
+ handle->priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+ handle->priv.iso14443a.state = ISO14443A_STATE_SELECTED;
+
+ {
+ int uid_len;
+ if (uid_size == 1)
+ uid_len = 4;
+ else if (uid_size == 2)
+ uid_len = 7;
+ else
+ uid_len = 10;
+
+ DEBUGP("UID %s\n", rfid_hexdump(uid, uid_len));
+ }
+
+ if (sak[0] & 0x20) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ handle->priv.iso14443a.tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ handle->priv.iso14443a.tcl_capable = 0;
+ }
+
+ return 0;
+}
+
+static int
+iso14443a_hlta(struct rfid_layer2_handle *handle)
+{
+ int ret;
+ unsigned char tx_buf[2] = { 0x50, 0x00 };
+ unsigned char rx_buf[10];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ ret = iso14443a_transcieve(handle, tx_buf, sizeof(tx_buf),
+ rx_buf, &rx_len, 1000 /* 1ms */, 0);
+ if (ret < 0) {
+ /* "error" case: we don't get somethng back from the card */
+ return 0;
+ }
+ return -1;
+}
+
+static struct rfid_layer2_handle *
+iso14443a_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso14443a;
+ h->rh = rh;
+ h->priv.iso14443a.state = ISO14443A_STATE_NONE;
+ h->priv.iso14443a.level = ISO14443A_LEVEL_NONE;
+
+ ret = h->rh->reader->iso14443a.init(h->rh);
+ if (ret < 0) {
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso14443a_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+
+struct rfid_layer2 rfid_layer2_iso14443a = {
+ .id = RFID_LAYER2_ISO14443A,
+ .name = "ISO 14443-3 A",
+ .fn = {
+ .init = &iso14443a_init,
+ .open = &iso14443a_anticol,
+ .transcieve = &iso14443a_transcieve,
+ .close = &iso14443a_hlta,
+ .fini = &iso14443a_fini,
+ },
+};
+
diff --git a/rfid_layer2_iso14443b.c b/rfid_layer2_iso14443b.c
new file mode 100644
index 0000000..c785826
--- /dev/null
+++ b/rfid_layer2_iso14443b.c
@@ -0,0 +1,309 @@
+/* ISO 14443-3 B anticollision implementation
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_layer2_iso14443b.h>
+
+#include "rfid_iso14443_common.h"
+
+#define ATQB_TIMEOUT ((256*10e6/ISO14443_FREQ_SUBCARRIER) \
+ +(200*10e6/ISO14443_FREQ_SUBCARRIER))
+
+static inline int
+fwi_to_fwt(struct rfid_layer2_handle *h, unsigned int *fwt, unsigned int fwi)
+{
+ if (fwi > 14)
+ return -1;
+
+ return (256 * 16 / h->rh->ah->asic->fc) * 2 ^ fwi;
+}
+
+static int
+parse_atqb(struct rfid_layer2_handle *h, struct iso14443b_atqb *atqb)
+{
+ int ret;
+
+ if (atqb->fifty != 0x50)
+ return -1;
+
+ if (atqb->protocol_info.fo & 0x01)
+ h->priv.iso14443b.flags |= ISO14443B_CID_SUPPORTED;
+ if (atqb->protocol_info.fo & 0x02)
+ h->priv.iso14443b.flags |= ISO14443B_NAD_SUPPORTED;
+
+ ret = fwi_to_fwt(h, &h->priv.iso14443b.fwt, atqb->protocol_info.fwi);
+ if (ret < 0) {
+ DEBUGP("invalid fwi %u\n", atqb->protocol_info.fwi);
+ return ret;
+ }
+
+ if (atqb->protocol_info.protocol_type == 0x1) {
+ DEBUGP("we have a T=CL compliant PICC\n");
+ h->priv.iso14443b.tcl_capable = 1;
+ } else {
+ DEBUGP("we have a T!=CL PICC\n");
+ h->priv.iso14443b.tcl_capable = 0;
+ }
+
+ iso14443_fsdi_to_fsd(&h->priv.iso14443b.fsc,
+ atqb->protocol_info.max_frame_size);
+
+ /* FIXME: speed capability */
+
+ memcpy(h->priv.iso14443b.pupi, atqb->pupi,
+ sizeof(h->priv.iso14443b.pupi));
+
+ return 0;
+}
+
+static int
+send_reqb(struct rfid_layer2_handle *h, unsigned char afi,
+ unsigned int is_wup, unsigned int num_initial_slots)
+{
+ int ret;
+ unsigned char reqb[3];
+ struct iso14443b_atqb atqb;
+ unsigned int atqb_len = sizeof(atqb);
+ unsigned int num_slot_idx = num_initial_slots;
+
+ reqb[0] = 0x05;
+ reqb[1] = afi;
+
+ for (num_slot_idx = num_initial_slots; num_slot_idx <= 4;
+ num_slot_idx++) {
+ reqb[2] = num_slot_idx & 0x07;
+ if (is_wup)
+ reqb[2] |= 0x80;
+
+ ret = h->rh->reader->transcieve(h->rh, reqb, sizeof(reqb),
+ (unsigned char *)&atqb,
+ &atqb_len, ATQB_TIMEOUT, 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_REQB_SENT;
+ if (ret < 0) {
+ DEBUGP("error during transcieve of REQB/WUBP\n");
+ continue;
+ }
+
+ /* FIXME: send N-1 slot marker frames */
+
+ if (atqb_len != sizeof(atqb)) {
+ DEBUGP("error: atqb_len = %u instead of %u\n",
+ atqb_len, sizeof(atqb));
+ continue;
+ }
+
+ /* FIXME: how to detect a collission at 14443B ? I guess we
+ * can only rely on the CRC checking (CRCErr in ErrorFlag
+ * register?) */
+
+ if (parse_atqb(h, &atqb) >= 0) {
+ h->priv.iso14443b.state = ISO14443B_STATE_ATQB_RCVD;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static inline unsigned int mbli_to_mbl(struct rfid_layer2_handle *h,
+ unsigned int mbli)
+{
+ return (h->priv.iso14443b.fsc * 2 ^ (mbli-1));
+}
+
+static int
+transcieve_attrib(struct rfid_layer2_handle *h, const unsigned char *inf,
+ unsigned int inf_len, unsigned char *rx_data, unsigned int *rx_len)
+{
+ struct iso14443b_attrib_hdr *attrib;
+ unsigned int attrib_size = sizeof(*attrib) + inf_len;
+ unsigned char *rx_buf;
+ unsigned char fsdi;
+ int ret = 0;
+
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+ attrib = malloc(attrib_size);
+ if (!attrib) {
+ perror("attrib_alloc");
+ return -1;
+ }
+
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+ rx_buf = malloc(*rx_len+1);
+ if (!rx_buf) {
+ perror("rx_buf malloc");
+ ret = -1;
+ goto out_attrib;
+ }
+
+ /* initialize attrib frame */
+ memset(attrib, 0, attrib_size);
+ if (inf_len)
+ memcpy((unsigned char *)attrib+sizeof(*attrib), inf, inf_len);
+
+ attrib->one_d = 0x1d;
+ memcpy(attrib->identifier, h->priv.iso14443b.pupi, 4);
+
+ /* FIXME: do we want to change TR0/TR1 from its default ? */
+ /* FIXME: do we want to change SOF/EOF from its default ? */
+
+ ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.iso14443b.fsd);
+ if (ret < 0) {
+ DEBUGP("unable to map FSD(%u) to FSDI\n",
+ h->priv.iso14443b.fsd);
+ goto out_rx;
+ }
+ attrib->param2.fsdi = fsdi;
+
+ /* FIXME: spd_in / spd_out */
+ if (h->priv.iso14443b.tcl_capable == 1)
+ attrib->param3.protocol_type = 0x1;
+
+ *rx_len = *rx_len + 1;
+ ret = h->rh->reader->transcieve(h->rh, (unsigned char *) attrib,
+ sizeof(*attrib)+inf_len,
+ rx_buf, rx_len, h->priv.iso14443b.fwt,
+ 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_ATTRIB_SENT;
+ if (ret < 0) {
+ DEBUGP("transcieve problem\n");
+ goto out_rx;
+ }
+
+ if ((rx_buf[0] & 0x0f) != h->priv.iso14443b.cid) {
+ DEBUGP("ATTRIB response with invalid CID %u\n",
+ rx_buf[0] & 0x0f);
+ ret = -1;
+ goto out_rx;
+ }
+
+ h->priv.iso14443b.state = ISO14443B_STATE_SELECTED;
+
+ h->priv.iso14443b.mbl = mbli_to_mbl(h, (rx_data[0] & 0xf0) >> 4);
+
+ *rx_len = *rx_len - 1;
+ memcpy(rx_data, rx_buf+1, *rx_len);
+
+out_rx:
+ free(rx_buf);
+out_attrib:
+ free(attrib);
+
+ return ret;
+}
+
+static int
+iso14443b_hltb(struct rfid_layer2_handle *h)
+{
+ int ret;
+ unsigned char hltb[5];
+ unsigned char hltb_resp[1];
+ unsigned int hltb_len = 1;
+
+ hltb[0] = 0x50;
+ memcpy(hltb+1, h->priv.iso14443b.pupi, 4);
+
+ ret = h->rh->reader->transcieve(h->rh, hltb, 5,
+ hltb_resp, &hltb_len,
+ h->priv.iso14443b.fwt, 0);
+ h->priv.iso14443b.state = ISO14443B_STATE_HLTB_SENT;
+ if (ret < 0) {
+ DEBUGP("transcieve problem\n");
+ return ret;
+ }
+
+ if (hltb_len != 1 || hltb_resp[0] != 0x00) {
+ DEBUGP("bad HLTB response\n");
+ return -1;
+ }
+ h->priv.iso14443b.state = ISO14443B_STATE_HALTED;
+
+ return 0;
+}
+
+static int
+iso14443b_anticol(struct rfid_layer2_handle *handle)
+{
+ unsigned char afi = 0; /* FIXME */
+ int ret;
+ char buf[255];
+ unsigned int buf_len = sizeof(buf);
+
+ ret = send_reqb(handle, afi, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = transcieve_attrib(handle, NULL, 0, buf, &buf_len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct rfid_layer2_handle *
+iso14443b_init(struct rfid_reader_handle *rh)
+{
+ int ret;
+ struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ h->l2 = &rfid_layer2_iso14443b;
+ h->rh = rh;
+ h->priv.iso14443b.state = ISO14443B_STATE_NONE;
+
+ h->priv.iso14443b.fsd = iso14443_fsd_approx(rh->ah->mru);
+ DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
+
+ /* 14443-3 Section 7.1.6 */
+ h->priv.iso14443b.tr0 = (256/ISO14443_FREQ_SUBCARRIER)*10e6;
+ h->priv.iso14443b.tr1 = (200/ISO14443_FREQ_SUBCARRIER)*10e6;
+
+ ret = h->rh->reader->iso14443b.init(h->rh);
+ if (ret < 0) {
+ DEBUGP("error during reader 14443b init\n");
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+static int
+iso14443b_fini(struct rfid_layer2_handle *handle)
+{
+ free(handle);
+ return 0;
+}
+
+static int
+iso14443b_transcieve(struct rfid_layer2_handle *handle,
+ const unsigned char *tx_buf, unsigned int tx_len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return handle->rh->reader->transcieve(handle->rh, tx_buf, tx_len,
+ rx_buf, rx_len, timeout, flags);
+}
+
+struct rfid_layer2 rfid_layer2_iso14443b = {
+ .id = RFID_LAYER2_ISO14443B,
+ .name = "ISO 14443-3 B",
+ .fn = {
+ .init = &iso14443b_init,
+ .open = &iso14443b_anticol,
+ .transcieve = &iso14443b_transcieve,
+ .close = &iso14443b_hltb,
+ .fini = &iso14443b_fini,
+ },
+};
+
diff --git a/rfid_proto_tcl.c b/rfid_proto_tcl.c
new file mode 100644
index 0000000..299360e
--- /dev/null
+++ b/rfid_proto_tcl.c
@@ -0,0 +1,448 @@
+/* ISO 14443-4 (T=CL) implementation, PCD side.
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_protocol_tcl.h>
+#include <rfid/rfid_protocol.h>
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_layer2_iso14443b.h>
+
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_reader.h>
+
+#include "rfid_iso14443_common.h"
+
+
+static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h,
+ unsigned char sfgi)
+{
+ /* ISO 14443-4:2000(E) Section 5.2.5. */
+ return (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi);
+}
+
+static unsigned int fwi_to_fwt(struct rfid_protocol_handle *h,
+ unsigned char fwi)
+{
+ /* ISO 14443-4:2000(E) Section 7.2. */
+ return (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi);
+}
+
+#define activation_fwt(x) (65536 / x->l2h->rh->ah->fc)
+#define deactivation_fwt(x) activation_fwt(x)
+
+static int
+tcl_parse_ats(struct rfid_protocol_handle *h,
+ unsigned char *ats, unsigned int size)
+{
+ unsigned char len = ats[0];
+ unsigned char t0;
+ unsigned char *cur;
+
+ if (len == 0 || size == 0)
+ return -1;
+
+ if (size < len)
+ len = size;
+
+ if (len == 1) {
+ /* FIXME: assume some default values */
+ h->priv.tcl.fsc = 32;
+ h->priv.tcl.ta = 0;
+ h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0);
+ if (1 /* FIXME: is_iso14443a */) {
+ /* Section 7.2: fwi default for type A is 4 */
+ h->priv.tcl.fwt = fwi_to_fwt(h, 4);
+ } else {
+ /* Section 7.2: fwi for type B is always in ATQB */
+ /* FIXME */
+ }
+ return 0;
+ }
+
+ /* guarateed to be at least 2 bytes in size */
+
+ t0 = ats[1];
+ cur = &ats[2];
+
+ iso14443_fsdi_to_fsd(&h->priv.tcl.fsc, t0 & 0x0f);
+
+ if (t0 & (1 << 4)) {
+ /* TA is transmitted */
+ h->priv.tcl.ta = *cur++;
+ }
+
+ if (t0 & (1 << 5)) {
+ /* TB is transmitted */
+ h->priv.tcl.sfgt = sfgi_to_sfgt(h, *cur & 0x0f);
+ h->priv.tcl.fwt = fwi_to_fwt(h, (*cur & 0xf0) >> 4);
+ cur++;
+ }
+
+ if (t0 & (1 << 6)) {
+ /* TC is transmitted */
+ if (*cur & 0x01)
+ h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
+ if (*cur & 0x02)
+ h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
+ cur++;
+ }
+
+ h->priv.tcl.historical_len = (ats+len) - cur;
+ h->priv.tcl.historical_bytes = cur;
+
+ return 0;
+}
+
+
+/* request an ATS from the PICC */
+static int
+tcl_request_ats(struct rfid_protocol_handle *h)
+{
+ int ret;
+ unsigned char rats[2];
+ unsigned char fsdi;
+
+ if (h->priv.tcl.state != TCL_STATE_INITIAL)
+ return -1;
+
+ ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.tcl.fsd);
+ if (ret < 0) {
+ DEBUGP("unable to encode FSD of %u as FSDI\n", h->priv.tcl.fsd);
+ return ret;
+ }
+
+ rats[0] = 0xe0;
+ rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0);
+
+ /* transcieve (with CRC) */
+ ret = h->l2h->l2->fn.transcieve(h->l2h, rats, 2, h->priv.tcl.ats,
+ &h->priv.tcl.ats_len, activation_fwt(h),
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0) {
+ DEBUGP("transcieve of rats failed\n");
+ h->priv.tcl.state = TCL_STATE_RATS_SENT;
+ /* FIXME: retransmit */
+ return ret;
+ }
+ h->priv.tcl.state = TCL_STATE_ATS_RCVD;
+
+ ret = tcl_parse_ats(h, h->priv.tcl.ats, h->priv.tcl.ats_len);
+ if (ret < 0) {
+ DEBUGP("parsing of ats failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+/* start a PSS run (autimatically configure highest possible speed */
+static int
+tcl_do_pss(struct rfid_protocol_handle *h)
+{
+ unsigned char ppss[3];
+ unsigned char pps_response[1];
+
+ if (h->priv.tcl.state != TCL_STATE_ATS_RCVD)
+ return -1;
+
+ /* ISO 14443-4:2000(E) Section 5.3. */
+
+ ppss[0] = 0xd0 & (h->priv.tcl.cid & 0x0f);
+ ppss[1] = 0x11;
+
+ //ppss[2] = 0x00 & foo;
+
+ // FIXME: finish
+
+ return -1;
+
+ h->priv.tcl.state = TCL_STATE_ESTABLISHED;
+}
+
+
+static int
+tcl_build_prologue2(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len,
+ unsigned char pcb)
+{
+ *prlg_len = 1;
+
+ *prlg = pcb;
+
+ if (th->flags & TCL_HANDLE_F_CID_USED) {
+ /* ISO 14443-4:2000(E) Section 7.1.1.2 */
+ *prlg |= TCL_PCB_CID_FOLLOWING;
+ (*prlg_len)++;
+ prlg[*prlg_len] = th->cid & 0x0f;
+ }
+
+ /* nad only for I-block (0xc0 == 00) */
+ if ((th->flags & TCL_HANDLE_F_NAD_USED) &&
+ ((pcb & 0xc0) == 0x00)) {
+ /* ISO 14443-4:2000(E) Section 7.1.1.3 */
+ /* FIXME: in case of chaining only for first frame */
+ *prlg |= TCL_PCB_NAD_FOLLOWING;
+ prlg[*prlg_len] = th->nad;
+ (*prlg_len)++;
+ }
+
+ return 0;
+}
+
+static int
+tcl_build_prologue_i(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len)
+{
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+ return tcl_build_prologue2(th, prlg, prlg_len, 0x02);
+}
+
+static int
+tcl_build_prologue_r(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len,
+ unsigned int nak)
+{
+ unsigned char pcb = 0xa2;
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+
+ if (nak)
+ pcb |= 0x10;
+
+ return tcl_build_prologue2(th, prlg, prlg_len, pcb);
+}
+
+static int
+tcl_build_prologue_s(struct tcl_handle *th,
+ unsigned char *prlg, unsigned int *prlg_len)
+{
+ /* ISO 14443-4:2000(E) Section 7.1.1.1 */
+
+ /* the only S-block from PCD->PICC is DESELECT: */
+ return tcl_build_prologue2(th, prlg, prlg_len, 0xc2);
+}
+
+/* FIXME: WTXM implementation */
+
+static int tcl_prlg_len(struct tcl_handle *th)
+{
+ int prlg_len = 1;
+
+ if (th->flags & TCL_HANDLE_F_CID_USED)
+ prlg_len++;
+
+ if (th->flags & TCL_HANDLE_F_NAD_USED)
+ prlg_len++;
+
+ return prlg_len;
+}
+
+#define max_net_tx_framesize(x) (x->fsc - tcl_prlg_len(x))
+
+static int
+tcl_connect(struct rfid_protocol_handle *h)
+{
+ int ret;
+
+ if (h->priv.tcl.state != TCL_STATE_DESELECTED &&
+ h->priv.tcl.state != TCL_STATE_INITIAL)
+ return -1;
+
+ switch (h->l2h->l2->id) {
+ case RFID_LAYER2_ISO14443A:
+ /* Start Type A T=CL Activation Sequence */
+ ret = tcl_request_ats(h);
+ if (ret < 0)
+ return ret;
+
+ if (0 /* FIXME */) {
+ ret = tcl_do_pss(h);
+ if (ret < 0)
+ return -1;
+ }
+ break;
+ case RFID_LAYER2_ISO14443B:
+ /* initialized T=CL state from Type B Activation Data */
+ h->priv.tcl.cid = h->l2h->priv.iso14443b.cid;
+ h->priv.tcl.fsc = h->l2h->priv.iso14443b.fsc;
+ h->priv.tcl.fsd = h->l2h->priv.iso14443b.fsd;
+ h->priv.tcl.fwt = h->l2h->priv.iso14443b.fwt;
+
+ /* what about ta? sfgt? */
+
+ if (h->l2h->priv.iso14443b.flags & ISO14443B_CID_SUPPORTED)
+ h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
+ if (h->l2h->priv.iso14443b.flags & ISO14443B_NAD_SUPPORTED)
+ h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
+
+ switch (h->l2h->priv.iso14443b.state) {
+ case ISO14443B_STATE_SELECTED:
+ h->priv.tcl.state = TCL_STATE_ATS_RCVD;
+ break;
+ case ISO14443B_STATE_ATTRIB_SENT:
+ h->priv.tcl.state = TCL_STATE_RATS_SENT;
+ break;
+ }
+
+ /* PUPI will be presented as ATS/historical bytes */
+ memcpy(h->priv.tcl.ats, h->l2h->priv.iso14443b.pupi, 4);
+ h->priv.tcl.ats_len = 4;
+ h->priv.tcl.historical_bytes = h->priv.tcl.ats;
+
+ break;
+ default:
+ DEBUGP("unsupported l2: %u\n", h->l2h->l2->id);
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+static int
+tcl_deselect(struct rfid_protocol_handle *h)
+{
+ /* ISO 14443-4:2000(E) Section 8 */
+ int ret;
+ unsigned char frame[3]; /* 3 bytes prologue, no information */
+ unsigned char rx[3];
+ unsigned int rx_len = sizeof(rx);
+ unsigned int prlg_len;
+ struct tcl_handle *th = &h->priv.tcl;
+
+ if (th->state != TCL_STATE_ESTABLISHED) {
+ /* FIXME: not sure whether deselect is possible here,
+ * probably better send a HLTA? */
+ }
+
+ /* build DESELECT S-block */
+ ret = tcl_build_prologue_s(th, frame, &prlg_len);
+ if (ret < 0)
+ return ret;
+
+ ret = h->l2h->l2->fn.transcieve(h->l2h, frame, prlg_len, rx,
+ &rx_len, deactivation_fwt(h),
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0) {
+ /* FIXME: retransmit, HLT(A|B) */
+ return ret;
+ }
+
+ th->state = TCL_STATE_DESELECTED;
+
+ return 0;
+}
+
+static int
+tcl_transcieve(struct rfid_protocol_handle *h,
+ const unsigned char *tx_data, unsigned int tx_len,
+ unsigned char *rx_data, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ int ret;
+ unsigned char *tx_buf, *rx_buf;
+ unsigned int prlg_len;
+ struct tcl_handle *th = &h->priv.tcl;
+
+ if (tx_len > max_net_tx_framesize(th)) {
+ /* slow path: we need to use chaining */
+ return -1;
+ }
+
+ tx_buf = malloc(tcl_prlg_len(th) + tx_len);
+ if (!tx_buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ rx_buf = malloc(tcl_prlg_len(th) + *rx_len);
+ if (!rx_buf) {
+ ret = -ENOMEM;
+ goto out_txb;
+ }
+
+ if (tcl_build_prologue_i(th, tx_buf, &prlg_len) < 0) {
+ ret = -1;
+ goto out_rxb;
+ }
+ memcpy(tx_buf + prlg_len, tx_data, tx_len);
+
+ ret = h->l2h->l2->fn.transcieve(h->l2h, tx_buf, tx_len+prlg_len,
+ rx_buf, rx_len, th->fwt, 0);
+ if (ret < 0)
+ goto out_rxb;
+
+
+ memcpy(rx_data, rx_buf, *rx_len);
+
+out_rxb:
+ free(rx_buf);
+out_txb:
+ free(tx_buf);
+out:
+ return ret;
+}
+
+#if 0
+int
+tcl_send(struct tcl_handle *th)
+{
+ return -1;
+}
+
+int
+tcl_recv()
+{
+ return -1;
+}
+#endif
+
+static struct rfid_protocol_handle *
+tcl_init(struct rfid_layer2_handle *l2h)
+{
+ struct rfid_protocol_handle *th;
+ unsigned int mru = l2h->rh->ah->mru;
+
+ th = malloc(sizeof(struct rfid_protocol_handle) + mru);
+ if (!th)
+ return NULL;
+
+ /* FIXME: mru should be attribute of layer2 (in case it adds/removes
+ * some overhead */
+ memset(th, 0, sizeof(struct rfid_protocol_handle) + mru);
+
+ /* maximum received ats length equals mru of asic/reader */
+ th->priv.tcl.state = TCL_STATE_INITIAL;
+ th->priv.tcl.ats_len = mru;
+ th->l2h = l2h;
+ th->proto = &rfid_protocol_tcl;
+
+ th->priv.tcl.fsd = iso14443_fsd_approx(mru);
+
+ return th;
+}
+
+static int
+tcl_fini(struct rfid_protocol_handle *ph)
+{
+ free(ph);
+ return 0;
+}
+
+struct rfid_protocol rfid_protocol_tcl = {
+ .id = RFID_PROTOCOL_TCL,
+ .name = "ISO 14443-4 / T=CL",
+ .fn = {
+ .init = &tcl_init,
+ .open = &tcl_connect,
+ .transcieve = &tcl_transcieve,
+ .close = &tcl_deselect,
+ .fini = &tcl_fini,
+ },
+};
diff --git a/rfid_protocol.c b/rfid_protocol.c
new file mode 100644
index 0000000..33aa10c
--- /dev/null
+++ b/rfid_protocol.c
@@ -0,0 +1,59 @@
+/* librfid - layer 3 protocol handler
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rfid/rfid_layer2.h>
+#include <rfid/rfid_protocol.h>
+
+static struct rfid_protocol *rfid_protocol_list;
+
+struct rfid_protocol_handle *
+rfid_protocol_init(struct rfid_layer2_handle *l2h, unsigned int id)
+{
+ struct rfid_protocol *p;
+
+ for (p = rfid_protocol_list; p; p = p->next)
+ if (p->id == id)
+ return p->fn.init(l2h);
+
+ return NULL;
+}
+
+int
+rfid_protocol_open(struct rfid_protocol_handle *ph)
+{
+ return ph->proto->fn.open(ph);
+}
+
+int
+rfid_protocol_transcieve(struct rfid_protocol_handle *ph,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return ph->proto->fn.transcieve(ph, tx_buf, len, rx_buf, rx_len,
+ timeout, flags);
+}
+
+int rfid_protocol_fini(struct rfid_protocol_handle *ph)
+{
+ return ph->proto->fn.fini(ph);
+}
+
+int
+rfid_protocol_close(struct rfid_protocol_handle *ph)
+{
+ return ph->proto->fn.close(ph);
+}
+
+int
+rfid_protocol_register(struct rfid_protocol *p)
+{
+ p->next = rfid_protocol_list;
+ rfid_protocol_list = p;
+
+ return 0;
+}
diff --git a/rfid_reader.c b/rfid_reader.c
new file mode 100644
index 0000000..834f926
--- /dev/null
+++ b/rfid_reader.c
@@ -0,0 +1,48 @@
+/* librfid - core reader handling
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_reader.h>
+
+static struct rfid_reader *rfid_reader_list;
+
+struct rfid_reader_handle *
+rfid_reader_open(void *data, unsigned int id)
+{
+ struct rfid_reader *p;
+
+ for (p = rfid_reader_list; p; p = p->next)
+ if (p->id == id)
+ return p->open(data);
+
+ DEBUGP("unable to find matching reader\n");
+ return NULL;
+}
+
+int
+rfid_reader_transcieve(struct rfid_reader_handle *rh,
+ const unsigned char *tx_buf, unsigned int len,
+ unsigned char *rx_buf, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return rh->reader->transcieve(rh, tx_buf, len, rx_buf, rx_len,
+ timeout, flags);
+}
+
+int
+rfid_reader_close(struct rfid_reader_handle *rh)
+{
+ return rh->reader->close(rh);
+}
+
+int
+rfid_reader_register(struct rfid_reader *r)
+{
+ r->next = rfid_reader_list;
+ rfid_reader_list = r;
+
+ return 0;
+}
diff --git a/rfid_reader_cm5121.c b/rfid_reader_cm5121.c
new file mode 100644
index 0000000..30d1c67
--- /dev/null
+++ b/rfid_reader_cm5121.c
@@ -0,0 +1,276 @@
+/* Omnikey CardMan 5121 specific RC632 transport layer
+ *
+ * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * The 5121 is an Atmel AT98C5122 based USB CCID reader (probably the same
+ * design like the 3121). It's CL RC632 is connected via address/data bus,
+ * not via SPI.
+ *
+ * The vendor-supplied reader firmware provides some undocumented extensions
+ * to CCID (via PC_to_RDR_Escape) that allow access to registers and FIFO of
+ * the RC632.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rfid/rfid.h>
+#include <rfid/rfid_reader.h>
+#include <rfid/rfid_asic.h>
+#include <rfid/rfid_asic_rc632.h>
+#include <rfid/rfid_reader_cm5121.h>
+
+#define SENDBUF_LEN 40
+#define RECVBUF_LEN 40
+
+static
+int Write1ByteToReg(struct rfid_asic_transport_handle *rath,
+ unsigned char reg, unsigned char value)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char rcvbuf[RECVBUF_LEN];
+ unsigned int retlen = RECVBUF_LEN;
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x01;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x00;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = reg;
+ sndbuf[7] = value;
+
+ DEBUGP("reg=0x%02x, val=%02x\n", reg, value);
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 8, rcvbuf,
+ &retlen) == 0)
+ return 0;
+
+ return -1;
+}
+
+static int Read1ByteFromReg(struct rfid_asic_transport_handle *rath,
+ unsigned char reg,
+ unsigned char *value)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[RECVBUF_LEN];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x00;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x01;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = reg;
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 7, recvbuf,
+ &retlen) == 0) {
+ *value = recvbuf[1];
+ DEBUGP("reg=0x%02x, val=%02x\n", reg, *value);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int ReadNBytesFromFIFO(struct rfid_asic_transport_handle *rath,
+ unsigned char num_bytes,
+ unsigned char *buf)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[0x7f];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = 0x00;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = num_bytes;
+ sndbuf[5] = 0x00;
+ sndbuf[6] = 0x02;
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, 7, recvbuf, &retlen) == 0) {
+ DEBUGP("%s\n", rfid_hexdump(recvbuf+1, num_bytes));
+ memcpy(buf, recvbuf+1, num_bytes); // len == 0x7f
+ return 0;
+ }
+
+ return -1;
+}
+
+static int WriteNBytesToFIFO(struct rfid_asic_transport_handle *rath,
+ unsigned char len,
+ const unsigned char *bytes,
+ unsigned char flags)
+{
+ unsigned char sndbuf[SENDBUF_LEN];
+ unsigned char recvbuf[0x7f];
+ unsigned int retlen = sizeof(recvbuf);
+
+ sndbuf[0] = 0x20;
+ sndbuf[1] = 0x00;
+ sndbuf[2] = len;
+ sndbuf[3] = 0x00;
+ sndbuf[4] = 0x00;
+ sndbuf[5] = flags;
+ sndbuf[6] = 0x02;
+
+ DEBUGP("%s\n", rfid_hexdump(bytes, len));
+
+ memcpy(sndbuf+7, bytes, len);
+
+ if (PC_to_RDR_Escape(rath->data, sndbuf, len+7, recvbuf, &retlen) == 0) {
+ return 0;
+ }
+
+ return -1;
+}
+
+#if 0
+static int TestFIFO(struct rc632_handle *handle)
+{
+ unsigned char sndbuf[60]; // 0x3c
+
+ // FIXME: repne stosd, call
+
+ memset(sndbuf, 0, sizeof(sndbuf));
+
+ if (WriteNBytesToFIFO(handle, sizeof(sndbuf), sndbuf, 0) < 0)
+ return -1;
+
+ return ReadNBytesFromFIFO(handle, sizeof(sndbuf), sndbuf);
+}
+#endif
+
+static int cm5121_transcieve(struct rfid_reader_handle *rh,
+ const unsigned char *tx_data, unsigned int tx_len,
+ unsigned char *rx_data, unsigned int *rx_len,
+ unsigned int timeout, unsigned int flags)
+{
+ return rh->ah->asic->priv.rc632.fn.transcieve(rh->ah, tx_data,
+ tx_len, rx_data,
+ rx_len, timeout,
+ flags);
+}
+
+static int cm5121_transcieve_sf(struct rfid_reader_handle *rh,
+ unsigned char cmd, struct iso14443a_atqa *atqa)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.transcieve_sf(rh->ah,
+ cmd,
+ (unsigned char *) atqa);
+}
+
+static int
+cm5121_transcieve_acf(struct rfid_reader_handle *rh, struct iso14443a_anticol_cmd *cmd,
+ unsigned int *bit_of_col)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.transcieve_acf(rh->ah,
+ cmd, bit_of_col);
+}
+
+static int
+cm5121_14443a_init(struct rfid_reader_handle *rh)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443a.init(rh->ah);
+}
+
+static int
+cm5121_14443b_init(struct rfid_reader_handle *rh)
+{
+ return rh->ah->asic->priv.rc632.fn.iso14443b.init(rh->ah);
+}
+
+
+struct rfid_asic_transport cm5121_ccid = {
+ .name = "CM5121 OpenCT",
+ .priv.rc632 = {
+ .fn = {
+ .reg_write = &Write1ByteToReg,
+ .reg_read = &Read1ByteFromReg,
+ .fifo_write = &WriteNBytesToFIFO,
+ .fifo_read = &ReadNBytesFromFIFO,
+ },
+ },
+};
+
+static int cm5121_enable_rc632(struct rfid_asic_transport_handle *rath)
+{
+ unsigned char tx_buf[1] = { 0x01 };
+ unsigned char rx_buf[64];
+ unsigned int rx_len = sizeof(rx_buf);
+
+ PC_to_RDR_Escape(rath->data, tx_buf, 1, rx_buf, &rx_len);
+ printf("received %d bytes from 01 command\n", rx_len);
+
+ return 0;
+}
+
+static struct rfid_reader_handle *
+cm5121_open(void *data)
+{
+ struct rfid_reader_handle *rh;
+ struct rfid_asic_transport_handle *rath;
+
+ rh = malloc(sizeof(*rh));
+ if (!rh)
+ return NULL;
+ memset(rh, 0, sizeof(*rh));
+
+ rath = malloc(sizeof(*rath));
+ if (!rath)
+ goto out_rh;
+ memset(rath, 0, sizeof(*rath));
+
+ rath->rat = &cm5121_ccid;
+ rath->data = data;
+
+ rh->reader = &rfid_reader_cm5121;
+
+ if (cm5121_enable_rc632(rath) < 0)
+ goto out_rath;
+
+ rh->ah = rc632_open(rath);
+ if (!rh->ah)
+ goto out_rath;
+
+ DEBUGP("returning %p\n", rh);
+ return rh;
+
+out_rath:
+ free(rath);
+out_rh:
+ free(rh);
+
+ return NULL;
+}
+
+static void
+cm5121_close(struct rfid_reader_handle *rh)
+{
+ struct rfid_asic_transport_handle *rath = rh->ah->rath;
+ rc632_close(rh->ah);
+ free(rath);
+ free(rh);
+}
+
+struct rfid_reader rfid_reader_cm5121 = {
+ .name = "Omnikey CardMan 5121 RFID",
+ .open = &cm5121_open,
+ .close = &cm5121_close,
+ .transcieve = &cm5121_transcieve,
+ .iso14443a = {
+ .init = &cm5121_14443a_init,
+ .transcieve_sf = &cm5121_transcieve_sf,
+ .transcieve_acf = &cm5121_transcieve_acf,
+ },
+ .iso14443b = {
+ .init = &cm5121_14443b_init,
+ },
+};
+
+
personal git repositories of Harald Welte. Your mileage may vary