move librfid to new location in repository
authorHarald Welte <laforge@gnumonks.org>
Sun, 29 May 2005 18:05:31 +0000 (18:05 +0000)
committerHarald Welte <laforge@gnumonks.org>
Sun, 29 May 2005 18:05:31 +0000 (18:05 +0000)
git-svn-id: https://svn.gnumonks.org/trunk/librfid@1181 e0336214-984f-0b4b-a45f-81c69e1f0ede

31 files changed:
COPYING [new file with mode: 0644]
LICENSING [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
TODO [new file with mode: 0644]
include/rfid/rfid.h [new file with mode: 0644]
include/rfid/rfid_asic.h [new file with mode: 0644]
include/rfid/rfid_asic_rc632.h [new file with mode: 0644]
include/rfid/rfid_layer2.h [new file with mode: 0644]
include/rfid/rfid_layer2_iso14443a.h [new file with mode: 0644]
include/rfid/rfid_layer2_iso14443b.h [new file with mode: 0644]
include/rfid/rfid_protocol.h [new file with mode: 0644]
include/rfid/rfid_protocol_tcl.h [new file with mode: 0644]
include/rfid/rfid_reader.h [new file with mode: 0644]
include/rfid/rfid_reader_cm5121.h [new file with mode: 0644]
openct-escape.c [new file with mode: 0644]
rc632.h [new file with mode: 0644]
rfid.c [new file with mode: 0644]
rfid_asic_rc632.c [new file with mode: 0644]
rfid_asic_rc632_14443a.c [new file with mode: 0644]
rfid_asic_rc632_14443b.c [new file with mode: 0644]
rfid_asic_rc632_mifare.c [new file with mode: 0644]
rfid_iso14443_common.c [new file with mode: 0644]
rfid_iso14443_common.h [new file with mode: 0644]
rfid_layer2.c [new file with mode: 0644]
rfid_layer2_iso14443a.c [new file with mode: 0644]
rfid_layer2_iso14443b.c [new file with mode: 0644]
rfid_proto_tcl.c [new file with mode: 0644]
rfid_protocol.c [new file with mode: 0644]
rfid_reader.c [new file with mode: 0644]
rfid_reader_cm5121.c [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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 (file)
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 (file)
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 (file)
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 (file)
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 (file)
index 0000000..bf8d799
--- /dev/null
@@ -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 (file)
index 0000000..e336d01
--- /dev/null
@@ -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 (file)
index 0000000..f4c9fa1
--- /dev/null
@@ -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 (file)
index 0000000..40b9bff
--- /dev/null
@@ -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 (file)
index 0000000..400f951
--- /dev/null
@@ -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 (file)
index 0000000..72e6155
--- /dev/null
@@ -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 (file)
index 0000000..93b89c3
--- /dev/null
@@ -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 (file)
index 0000000..b913e80
--- /dev/null
@@ -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 (file)
index 0000000..d6ad3a1
--- /dev/null
@@ -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 (file)
index 0000000..8d9a312
--- /dev/null
@@ -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 (file)
index 0000000..ed28c8d
--- /dev/null
@@ -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 (file)
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 (file)
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 (file)
index 0000000..3d5b621
--- /dev/null
@@ -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 (file)
index 0000000..d6c0358
--- /dev/null
@@ -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 (file)
index 0000000..62aa224
--- /dev/null
@@ -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 (file)
index 0000000..9bfb0ae
--- /dev/null
@@ -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 (file)
index 0000000..aacb45d
--- /dev/null
@@ -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 (file)
index 0000000..848d983
--- /dev/null
@@ -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 (file)
index 0000000..eb7cb2d
--- /dev/null
@@ -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 (file)
index 0000000..fbad9d8
--- /dev/null
@@ -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 (file)
index 0000000..c785826
--- /dev/null
@@ -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 (file)
index 0000000..299360e
--- /dev/null
@@ -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 (file)
index 0000000..33aa10c
--- /dev/null
@@ -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 (file)
index 0000000..834f926
--- /dev/null
@@ -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 (file)
index 0000000..30d1c67
--- /dev/null
@@ -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,
+       },
+};
+
+