From 56ecf4776af355ccf48b835835a042477f5ac78a Mon Sep 17 00:00:00 2001 From: dedected Date: Mon, 29 Dec 2008 00:56:07 +0000 Subject: [PATCH] initial commit of the linux driver for the dosch and amand dect pcmcia card. Currently only the type II card is supported. git-svn-id: https://dedected.org/svn/trunk@3 8d8ab74c-27aa-4a3d-9bde-523a2bc1f624 --- com-on-air_cs-linux/LICENSE | 339 +++++++ com-on-air_cs-linux/Makefile | 46 + com-on-air_cs-linux/README | 37 + com-on-air_cs-linux/com_on_air.c | 823 +++++++++++++++++ com-on-air_cs-linux/com_on_air.h | 65 ++ com-on-air_cs-linux/com_on_air_user.h | 45 + com-on-air_cs-linux/dect.c | 318 +++++++ com-on-air_cs-linux/dect.h | 42 + com-on-air_cs-linux/dip_opcodes.h | 161 ++++ com-on-air_cs-linux/firmware/.h | 1 + com-on-air_cs-linux/firmware/Makefile | 37 + com-on-air_cs-linux/firmware/bin2c.c | 55 ++ .../firmware/sc14421_II_sniff_scan.asm | 110 +++ .../firmware/sc14421_II_sniff_sync.asm | 298 +++++++ com-on-air_cs-linux/firmware/sc14421_footer.h | 2 + com-on-air_cs-linux/firmware/sc14421_header.h | 3 + com-on-air_cs-linux/sc14421.c | 146 +++ com-on-air_cs-linux/sc14421.h | 50 ++ com-on-air_cs-linux/sc14421_firmware.c | 142 +++ com-on-air_cs-linux/sc14421_firmware.h | 7 + com-on-air_cs-linux/sc14421_sniffer.c | 828 ++++++++++++++++++ com-on-air_cs-linux/sc14421_sniffer.h | 75 ++ com-on-air_cs-linux/tools/Makefile | 9 + com-on-air_cs-linux/tools/coa_syncsniff.c | 199 +++++ com-on-air_cs-linux/tools/dect_c_channel.h | 158 ++++ com-on-air_cs-linux/tools/dect_cli.c | 671 ++++++++++++++ com-on-air_cs-linux/tools/dect_cli.h | 85 ++ com-on-air_cs-linux/tools/dectshark/Makefile | 6 + .../tools/dectshark/dectshark.cpp | 122 +++ .../tools/dectshark/foundinfo.cpp | 97 ++ .../tools/dectshark/foundinfo.h | 55 ++ com-on-air_cs-linux/tools/dectshark/gui.cpp | 247 ++++++ com-on-air_cs-linux/tools/dectshark/gui.h | 49 ++ com-on-air_cs-linux/tools/pcap2cchan.c | 246 ++++++ com-on-air_cs-linux/tools/pcapstein.c | 177 ++++ com-on-air_cs-linux/tools/pcapstein.h | 44 + 36 files changed, 5795 insertions(+) create mode 100644 com-on-air_cs-linux/LICENSE create mode 100644 com-on-air_cs-linux/Makefile create mode 100644 com-on-air_cs-linux/README create mode 100644 com-on-air_cs-linux/com_on_air.c create mode 100644 com-on-air_cs-linux/com_on_air.h create mode 100644 com-on-air_cs-linux/com_on_air_user.h create mode 100644 com-on-air_cs-linux/dect.c create mode 100644 com-on-air_cs-linux/dect.h create mode 100644 com-on-air_cs-linux/dip_opcodes.h create mode 100644 com-on-air_cs-linux/firmware/.h create mode 100644 com-on-air_cs-linux/firmware/Makefile create mode 100644 com-on-air_cs-linux/firmware/bin2c.c create mode 100644 com-on-air_cs-linux/firmware/sc14421_II_sniff_scan.asm create mode 100644 com-on-air_cs-linux/firmware/sc14421_II_sniff_sync.asm create mode 100644 com-on-air_cs-linux/firmware/sc14421_footer.h create mode 100644 com-on-air_cs-linux/firmware/sc14421_header.h create mode 100644 com-on-air_cs-linux/sc14421.c create mode 100644 com-on-air_cs-linux/sc14421.h create mode 100644 com-on-air_cs-linux/sc14421_firmware.c create mode 100644 com-on-air_cs-linux/sc14421_firmware.h create mode 100644 com-on-air_cs-linux/sc14421_sniffer.c create mode 100644 com-on-air_cs-linux/sc14421_sniffer.h create mode 100644 com-on-air_cs-linux/tools/Makefile create mode 100644 com-on-air_cs-linux/tools/coa_syncsniff.c create mode 100644 com-on-air_cs-linux/tools/dect_c_channel.h create mode 100644 com-on-air_cs-linux/tools/dect_cli.c create mode 100644 com-on-air_cs-linux/tools/dect_cli.h create mode 100644 com-on-air_cs-linux/tools/dectshark/Makefile create mode 100644 com-on-air_cs-linux/tools/dectshark/dectshark.cpp create mode 100644 com-on-air_cs-linux/tools/dectshark/foundinfo.cpp create mode 100644 com-on-air_cs-linux/tools/dectshark/foundinfo.h create mode 100644 com-on-air_cs-linux/tools/dectshark/gui.cpp create mode 100644 com-on-air_cs-linux/tools/dectshark/gui.h create mode 100644 com-on-air_cs-linux/tools/pcap2cchan.c create mode 100644 com-on-air_cs-linux/tools/pcapstein.c create mode 100644 com-on-air_cs-linux/tools/pcapstein.h diff --git a/com-on-air_cs-linux/LICENSE b/com-on-air_cs-linux/LICENSE new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/com-on-air_cs-linux/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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. + + , 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 Lesser General +Public License instead of this License. diff --git a/com-on-air_cs-linux/Makefile b/com-on-air_cs-linux/Makefile new file mode 100644 index 0000000..17b1c7c --- /dev/null +++ b/com-on-air_cs-linux/Makefile @@ -0,0 +1,46 @@ +NODE:=/dev/coa + +PCMCIA_SLOT:=1 + +-include pcmcia_slot.make + +ifneq ($(KERNELRELEASE),) + obj-m := com_on_air_cs.o + com_on_air_cs-objs := com_on_air.o sc14421.o sc14421_sniffer.o sc14421_firmware.o dect.o +else + KDIR ?= /lib/modules/`uname -r`/build/ + PWD := $(shell pwd) + +default: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +endif + +load: node + insmod ./com_on_air_cs.ko && \ + pccardctl insert $(PCMCIA_SLOT) + +unload: + pccardctl eject $(PCMCIA_SLOT) && \ + rmmod com_on_air_cs + +reload: + pccardctl eject $(PCMCIA_SLOT) && \ + rmmod com_on_air_cs && \ + insmod ./com_on_air_cs.ko && \ + pccardctl insert $(PCMCIA_SLOT) + +node: $(NODE) +$(NODE): + mknod $@ --mode 660 c 3564 0 ### 3564 == 0xDEC +# chgrp dect $(NODE) + +read: node coa_read + tools/coa_read + +watch: node coa_read + watch -n 0.2 ./tools/coa_read + +clean: + rm -rf com_on_air_cs.ko com_on_air_cs.mod.c .com_on_air* .sc14421* .tmp* Module.symvers modules.order *.o + diff --git a/com-on-air_cs-linux/README b/com-on-air_cs-linux/README new file mode 100644 index 0000000..3b3f986 --- /dev/null +++ b/com-on-air_cs-linux/README @@ -0,0 +1,37 @@ + + +!!! for scientific and research purposes only !!! + + +what +~~~~ + com_on_air_cs is a very basic driver for the Dosch & Amand com-on-air PCMCIA + DECT cards. + In the tools/ subdir you find userspace tools using the driver + +license +~~~~~~~ + GNU GENERAL PUBLIC LICENSE Version 2 + see LICENSE + +authors +~~~~~~~ + Matthias Wenzel + Andreas Schuler + +install +~~~~~~~ + make && make -C tools # compiles the driver and userspace tools + make node # create the /dev/coa character device + +running +~~~~~~~ + the most featurecomplete tool for now is dect_cli. it can dump pcap + formatted captures. just run it and type help. + + coa_syncsniff dumps pcap files on a given channel and RFPI + + pcap2cchan dumps C-channel information from pcap files + + pcapstein dumps all B-Fields found in a pcap file + diff --git a/com-on-air_cs-linux/com_on_air.c b/com-on-air_cs-linux/com_on_air.c new file mode 100644 index 0000000..1e5fb4e --- /dev/null +++ b/com-on-air_cs-linux/com_on_air.c @@ -0,0 +1,823 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +#include "com_on_air.h" +#include "com_on_air_user.h" /* ioctls ... */ +#include "sc14421.h" +#include "sc14421_sniffer.h" + + +MODULE_AUTHOR("Matthias Wenzel comonairmazzoo.de;" + "Andreas Schuler dectbadterrorist.com"); +MODULE_DESCRIPTION("Dosch&Amand COM-ON-AIR PCMCIA driver"); +MODULE_LICENSE("GPL"); + +#define COA_DEVICE_NAME "com_on_air_cs" +#define COA_FIFO_SIZE 65536 + +struct coa_info *dev; + + + +static int coa_open(struct inode *inode, struct file *filp) +{ + if (dev->open) + return -EBUSY; + dev->open = 1; + + return nonseekable_open(inode, filp); +} + +/* we use some "hidden" ioctls */ +#define COA_IOCTL_TEST0 0xF000 +#define COA_IOCTL_TEST1 0xF001 +#define COA_IOCTL_TEST2 0xF002 +#define COA_IOCTL_TEST3 0xF003 +#define COA_IOCTL_TEST4 0xF004 +#define COA_IOCTL_TEST5 0xF005 +#define COA_IOCTL_TEST6 0xF006 +#define COA_IOCTL_TEST7 0xF007 + +int coa_ioctl( + struct inode *inode, + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + + unsigned long __user * argp = (unsigned long __user *) arg; + + if (!dev->p_dev->dev_node) + return -EIO; + + switch (cmd) + { + case COA_IOCTL_MODE: + { + uint16_t mode; + if (copy_from_user(&mode, argp, sizeof(mode))) + { + printk(COA_DEVICE_NAME + ": invalid argument in ioctl()\n"); + return -EINVAL; + } + switch (mode & COA_MODEMASK) + { + case COA_MODE_IDLE: + printk("com_on_air_cs: stopping DIP\n"); + SC14421_stop_dip(dev->sc14421_base); + dev->operation_mode = mode; + + kfifo_reset(dev->rx_fifo); + kfifo_reset(dev->tx_fifo); + + break; + case COA_MODE_FP: + printk("FIXME: implement COA_MODE_FP ;)\n"); + break; + case COA_MODE_PP: + printk("FIXME: implement COA_MODE_PP ;)\n"); + break; + case COA_MODE_SNIFF: + + kfifo_reset(dev->rx_fifo); + kfifo_reset(dev->tx_fifo); + + /* activiate sniffer */ + + if (!dev->sniffer_config) + dev->sniffer_config = + kzalloc(sizeof(*dev->sniffer_config), + GFP_KERNEL); + if (!(dev->sniffer_config)) + return -ENOMEM; + + dev->sniffer_config->snifftype = mode & COA_SUBMODEMASK; + dev->sniffer_config->channel = 0; + dev->operation_mode = mode; + + sniffer_init(dev); + printk(COA_DEVICE_NAME": sniffer initialized\n"); + break; + case COA_MODE_JAM: + printk("FIXME: implement COA_MODE_JAM\n"); + break; + default: + printk("coa: invalid ioctl() value " + "for COA_IOCTL_MODE\n"); + return -EINVAL; + } + break; + } + case COA_IOCTL_RADIO: + printk("FIXME: implement COA_IOCTL_RADIO\n"); + break; + case COA_IOCTL_RX: + printk("FIXME: implement COA_IOCTL_RX\n"); + break; + case COA_IOCTL_TX: + printk("FIXME: implement COA_IOCTL_TX\n"); + break; + case COA_IOCTL_CHAN: + { + uint32_t channel; + if (copy_from_user(&channel, argp, sizeof(channel))) + { + printk(COA_DEVICE_NAME": invalid argument " + "in ioctl()\n"); + return -EINVAL; + } + + if (channel > 10) + return -EINVAL; + + switch (dev->operation_mode & COA_MODEMASK) + { + case COA_MODE_IDLE: + break; + case COA_MODE_FP: + /* FIXME: implement COA_MODE_FP ;) */ + break; + case COA_MODE_PP: + /* FIXME: implement COA_MODE_PP ;) */ + break; + case COA_MODE_SNIFF: + dev->sniffer_config->channel = channel; + break; + case COA_MODE_JAM: + printk("FIXME: implement COA_MODE_JAM\n"); + break; + default: + printk("coa: invalid ioctl() value " + "for COA_IOCTL_MODE\n"); + return -EINVAL; + } + + sniffer_init(dev); + break; + } + case COA_IOCTL_SLOT: + printk("FIXME: implement COA_IOCTL_SLOT\n"); + break; + case COA_IOCTL_RSSI: + printk("FIXME: implement COA_IOCTL_RSSI\n"); + break; + case COA_IOCTL_FIRMWARE: + printk("FIXME: implement COA_IOCTL_FIRMWARE\n"); + break; + case COA_IOCTL_SETRFPI: + { + uint8_t RFPI[5]; + if (copy_from_user(&RFPI, argp, sizeof(RFPI))) + { + printk(COA_DEVICE_NAME": invalid argument in ioctl()\n"); + return -EINVAL; + } + + switch (dev->operation_mode & COA_MODEMASK) + { + case COA_MODE_IDLE: + break; + case COA_MODE_FP: + /* FIXME: implement COA_MODE_FP ;) */ + break; + case COA_MODE_PP: + /* FIXME: implement COA_MODE_PP ;) */ + break; + case COA_MODE_SNIFF: + memcpy(dev->sniffer_config->RFPI, RFPI, sizeof(dev->sniffer_config->RFPI)); + break; + case COA_MODE_JAM: + printk("FIXME: implement COA_MODE_JAM\n"); + break; + default: + printk("coa: invalid ioctl() value for COA_IOCTL_MODE\n"); + return -EINVAL; + } + + break; + } + case COA_IOCTL_TEST7: + case COA_IOCTL_TEST6: + case COA_IOCTL_TEST5: + case COA_IOCTL_TEST4: + case COA_IOCTL_TEST3: + case COA_IOCTL_TEST2: + { + printk("\n\ncom_on_air_cs: saw %d interrupts since loading\n\n\n", + dev->irq_count); + break; + } + case COA_IOCTL_TEST1: + { + static char teststring[] = "awake. " + "shake dreams from your head my pretty child, " + "my swet one. choose the day " + "and choose the sign of your day. " + "the day's divinity.\n"; + static char * ps = teststring; + int ret; + ret = kfifo_put(dev->rx_fifo, ps, 1); + if (ret <= 0) + printk("com_on_air_cs: rx fifo full? " + "kfifo_put() = %d\n", ret); + ps++; + if (!*ps) + ps = teststring; + break; + } + case COA_IOCTL_TEST0: + { + unsigned char bank; + int a, b, i; + printk("dumping complete DIP-RAM\n"); + disable_irq(dev->irq); + for (i = 0; i < 8; i++) + { + bank = (4 * i); + SC14421_switch_to_bank(dev->sc14421_base, bank); + + printk("Setting Banking-Register to %.2x\n\n", bank); + for (a = 0; a < 16; a++) + { + unsigned short *sc14421_base = dev->sc14421_base; + for (b = 0; b < 16; b++) + printk("%.2x ", + (unsigned char) + SC14421_READ( a*16 + b) ); +#if 0 + if (SC14421_READ(511) & 0x0f) + printk("%.2x ", + (unsigned char) + (SC14421_READ(511))); + printk("\n"); +#endif + } + } + enable_irq(dev->irq); + break; + } + default: + printk("coa: invalid ioctl()\n"); + return -EINVAL; + } + return 0; +} + +static unsigned int coa_poll(struct file *file, poll_table * wait) +{ + unsigned int mask = 0; + + if (!dev->p_dev->dev_node) + return -EIO; + + if (kfifo_len(dev->rx_fifo)) + mask |= POLLIN | POLLRDNORM; + if (COA_FIFO_SIZE - kfifo_len(dev->tx_fifo)) + mask |= POLLOUT | POLLWRNORM; + return mask; +} + +static ssize_t coa_read( + struct file *filp, + char __user *buf, + size_t count_want, + loff_t *ppos) +{ + size_t to_copy; + size_t not_copied; + unsigned char *data; + + if (!dev->p_dev->dev_node) + return -EIO; + + to_copy = min(kfifo_len(dev->rx_fifo), count_want); + data = kmalloc(to_copy, GFP_KERNEL); + if (!data) + return -ENOMEM; + + to_copy = kfifo_get(dev->rx_fifo, data, to_copy); + if (to_copy < 0) { + kfree(data); + return -EIO; + } + + not_copied = copy_to_user(buf, data, to_copy); + kfree(data); + + return to_copy - not_copied; +} + + +static int coa_close(struct inode *inode, struct file *filp) +{ + if (!dev->p_dev->dev_node) + return -EIO; + SC14421_stop_dip(dev->sc14421_base); + + dev->open = 0; + + kfifo_reset(dev->rx_fifo); + kfifo_reset(dev->tx_fifo); + + return 0; +} + + +static const struct file_operations coa_fops = +{ + .owner = THIS_MODULE, + .open = coa_open, + .ioctl = coa_ioctl, + .poll = coa_poll, + .read = coa_read, + .release = coa_close, +}; + +/**********************************************************************/ + +static int com_on_air_suspend (struct pcmcia_device *link) +{ + return 0; +} +static int com_on_air_resume (struct pcmcia_device *link) +{ + return 0; +} + +static irqreturn_t +com_on_air_irq_handler(int irq, void *dev_id) +{ + struct coa_info * dev = dev_id; + jiffies_to_timespec(jiffies, &dev->irq_timestamp); + dev->irq_count++; + + switch(dev->operation_mode & COA_MODEMASK) + { + case COA_MODE_FP: + /*station_irq_handler(dev); */ + break; + case COA_MODE_PP: + /*phone_irq_handler(dev); */ + break; + case COA_MODE_SNIFF: + sniffer_irq_handler(dev); + break; + default: + if (dev->sc14421_base) + SC14421_clear_interrupt(dev->sc14421_base); + } + + return IRQ_HANDLED; +} + +static int com_on_air_probe (struct pcmcia_device *link) +{ + win_req_t req; + int ret; + + dev->p_dev = link; + link->priv = dev; + + link->dev_node = kzalloc(sizeof(*link->dev_node), GFP_KERNEL); + if (!link->dev_node) + return -ENOMEM; + + link->devname = kzalloc(strlen(COA_DEVICE_NAME), GFP_KERNEL); + if (!link->devname) + { + ret = -ENOMEM; + goto probe_out_5; + } + + sprintf(link->devname, COA_DEVICE_NAME); + sprintf(link->dev_node->dev_name, COA_DEVICE_NAME); + + printk("com_on_air_cs: >>>>>>>>>>>>>>>>>>>>>>>>\n"); + printk("com_on_air_cs: card in slot %s\n", link->devname); + + if (link->prod_id[0]) + printk("com_on_air_cs: prod_id[0] %s\n", + link->prod_id[0]); + if (link->prod_id[1]) + printk("com_on_air_cs: prod_id[1] %s\n", + link->prod_id[1]); + if (link->prod_id[2]) + printk("com_on_air_cs: prod_id[2] %s\n", + link->prod_id[2]); + if (link->prod_id[3]) + printk("com_on_air_cs: prod_id[3] %s\n", + link->prod_id[3]); + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.NumPorts1 = 16; + link->io.Attributes2 = 0; + + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = com_on_air_irq_handler; + link->irq.Instance = dev; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.ConfigIndex = 1; + link->conf.Present = PRESENT_OPTION; + link->conf.ConfigBase = 0x1020; + + + req.Attributes = WIN_DATA_WIDTH_16 | WIN_ENABLE; + req.Base = 0; + req.Size = 0x1000; + req.AccessSpeed = 0; + + ret = pcmcia_request_window(&link, &req, &link->win); + if (ret != CS_SUCCESS) + { + printk("couldn't pcmcia_request_window() = 0x%x\n", ret); + goto probe_out_4; + } + + dev->links[0] = link; + dev->memsize[0] = req.Size; + dev->membase[0] = ioremap_nocache(req.Base, req.Size); + + if (!dev->membase[0]) + { + printk("com_on_air_cs: ERROR: couldn't ioremap()\n"); + ret = -EIO; + goto probe_out_3; + } + printk("com_on_air_cs: ioremap()'d baseaddr %p\n", dev->membase[0]); + + link->conf.Present = PRESENT_OPTION; + link->socket->functions = 0; + + dev->irq_count = 0; + + ret = pcmcia_request_irq(link, &link->irq); + if (ret != CS_SUCCESS) + { + printk("\ncom_on_air_cs: unable to allocate IRQ %d, ret=%x\n", + link->irq.AssignedIRQ, ret); + dev->irq = -1; + goto probe_out_2; + } else { + printk("com_on_air_cs: registered IRQ %d\n", + link->irq.AssignedIRQ); + dev->irq = link->irq.AssignedIRQ; + } + + ret = pcmcia_request_configuration(link, &link->conf); + if (ret != CS_SUCCESS) + { + printk("could not pcmcia_request_configuration()\n"); + goto probe_out_1; + } + + ret = pcmcia_get_configuration_info(link, &(dev->config)); + if (ret == CS_SUCCESS) + { + printk("com_on_air_cs: %svalid client.\n", + (dev->config.Attributes & CONF_VALID_CLIENT) ? "":"in"); + printk("com_on_air_cs: type 0x%x\n", + link->socket->state); + printk("com_on_air_cs: function 0x%x\n", + dev->config.Function); + printk("com_on_air_cs: Attributes %d\n", + dev->config.Attributes); + printk("com_on_air_cs: Vcc %d\n", + dev->config.Vcc); + printk("com_on_air_cs: Vpp1 %d\n", + dev->config.Vpp1); + printk("com_on_air_cs: Vpp2 %d\n", + dev->config.Vpp2); + printk("com_on_air_cs: IntType %d\n", + dev->config.IntType); + printk("com_on_air_cs: ConfigBase 0x%x\n", + dev->config.ConfigBase); + printk("com_on_air_cs: Status %u, " + "Pin %u, " + "Copy %u, " + "Option %u, " + "ExtStatus %u\n", + dev->config.Status, + dev->config.Pin, + dev->config.Copy, + dev->config.Option, + dev->config.ExtStatus); + printk("com_on_air_cs: Present %d\n", + dev->config.Present); + printk("com_on_air_cs: CardValues 0x%x\n", + dev->config.CardValues); + printk("com_on_air_cs: AssignedIRQ 0x%x\n", + dev->config.AssignedIRQ); + printk("com_on_air_cs: IRQAttributes 0x%x\n", + dev->config.IRQAttributes); + printk("com_on_air_cs: BasePort1 0x%x\n", + dev->config.BasePort1); + printk("com_on_air_cs: NumPorts1 0x%x\n", + dev->config.NumPorts1); + printk("com_on_air_cs: Attributes1 0x%x\n", + dev->config.Attributes1); + printk("com_on_air_cs: BasePort2 0x%x\n", + dev->config.BasePort2); + printk("com_on_air_cs: NumPorts2 0x%x\n", + dev->config.NumPorts2); + printk("com_on_air_cs: Attributes2 0x%x\n", + dev->config.Attributes2); + printk("com_on_air_cs: IOAddrLines 0x%x\n", + dev->config.IOAddrLines); + printk("com_on_air_cs: has%s function_config\n", + (link->function_config) ? "":" no"); + } else { + printk("com_on_air_cs: pcmcia_get_configuration_info() " + "failed\n"); + goto probe_out_0; + } + + set_device_configbase(dev->config.ConfigBase); + + dev->sc14421_base = ((unsigned short*)(dev->membase[0])); + + ret = get_card_id(); + printk("com_on_air_cs: get_card_id() = %d\n", ret); + switch (ret) + { + case 0: + dev->radio_type = COA_RADIO_TYPE_II; + break; + case 1: + case 2: + dev->radio_type = COA_RADIO_TYPE_III; + break; + default: + printk("com_on_air_cs: ERROR; unknown radio type, " + "please update driver\n"); + } + dev->card_id = ret; + + printk("com_on_air_cs: -----------------------\n"); + + return 0; + +probe_out_0: + pcmcia_disable_device(link); +probe_out_1: + free_irq(dev->irq, dev); +probe_out_2: + iounmap(dev->membase[0]); +probe_out_3: + pcmcia_release_window(link->win); +probe_out_4: + kfree(link->devname); +probe_out_5: + kfree(link->dev_node); + link->dev_node = NULL; + return ret; +} + +static void com_on_air_remove(struct pcmcia_device *link) +{ + + int j; + + printk("com_on_air_cs: COM-ON-AIR card ejected\n"); + printk("com_on_air_cs: <<<<<<<<<<<<<<<<<<<<<<<\n"); + + if (dev->irq >= 0) + { + printk("com_on_air_cs: freeing interrupt %d\n", + dev->irq); + free_irq(dev->irq, dev); + } + + for (j=0; j<2; j++) + { + if (dev->membase[j]) + { + printk("com_on_air_cs: iounmap()ing membase[%d]\n", j); + iounmap(dev->membase[j]); + } + if (dev->links[j]) + if (dev->links[j]->win) + { + printk("com_on_air_cs: releasing window %d\n", + j); + pcmcia_release_window(dev->links[j]->win); + } + } + + printk("com_on_air_cs: pcmcia_disable_device()\n"); + pcmcia_disable_device(link); + if (link->dev_node) + { + printk("com_on_air_cs: freeing dev_node\n"); + kfree(link->dev_node); + link->dev_node = 0; + } + if (link->devname) + { + printk("com_on_air_cs: freeing devname\n"); + kfree(link->devname); + link->devname = 0; + } + if (dev->sniffer_config) + { + printk("com_on_air_cs: freeing sniffer_config\n"); + kfree(dev->sniffer_config); + dev->sniffer_config = 0; + } +} + +static struct pcmcia_device_id com_on_air_ids[] = +{ + /* + * the crc32 hashes below are generated by the tool in + * Documentation/pcmcia/devicetable.txt + */ + PCMCIA_DEVICE_PROD_ID12 ("DECTDataDevice", "PCMCIA F22", + 0x11fe69e9, 0x253670b2), + PCMCIA_DEVICE_PROD_ID12 ("DECTDataDevice", "PCMCIA", + 0x11fe69e9, 0x281f1c5d), +#if 1 + PCMCIA_DEVICE_PROD_ID1234("DOSCH-AMAND", "MMAP PCMCIA", + "MXM500", "V1.00", + 0x4bc552e7, 0x0df519bb, + 0x09e43c7c, 0x3488c81a), +#endif + +#if 0 + There are more devices out there, I only own the above three. + an excerpt from win32 dna.inf: + +%String1%=pcmcia.install,PCMCIA\DOSCH-AMAND-MMAP_PCMCIA-C7D7 +%String1%=pcmcia.install,PCMCIA\Dosch-Amand-DECT_MultiMedia-BD0D +%String1%=pcmcia.install,PCMCIA\DOSCH_&_AMAND-DECT_MULTIMEDIA-1A9F +%String1%=pcmcia.install,PCMCIA\DECTDataDevice-F13-6433 +%String1%=pcmcia.install,PCMCIA\DECTDataDevice-PCMCIA-0EF8 +%String4%=pci.install,PCI\VEN_11E3&DEV_0001&SUBSYS_000111E3&REV_00 +%String4%=pci.install,PCI\VEN_11E3&DEV_0001&SUBSYS_00011786&REV_32 +%String4%=pci.install,PCI\VEN_1786&DEV_0001&SUBSYS_000111E3&REV_00 +%String5%=freekey2.install,PCMCIA\DECTDataDevice-PCMCIA-FEF2 +%String6%=freekey2.install,PCMCIA\DECTDataDevice-PCMCIA_F22-4BD3 +%String6%=freekey2.install,PCMCIA\DECTDataDevice-PCMCIA_F22-BBD9 + +#endif + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, com_on_air_ids); + +/* returns an index into com_on_air_ids[] */ +int get_card_id(void) +{ + u32 hash[4] = { 0, 0, 0, 0}; + int i; + int found = 0; + int ret = -1; + for (i=0; i<4; i++) + { + if (dev->p_dev->prod_id[i]) + hash[i] = crc32(0, + dev->p_dev->prod_id[i], + strlen(dev->p_dev->prod_id[i])); + } + + i = 0; + while(com_on_air_ids[i].match_flags) /* != PCMCIA_DEVICE_NULL */ + { + if ( (hash[0] == com_on_air_ids[i].prod_id_hash[0]) && + (hash[1] == com_on_air_ids[i].prod_id_hash[1]) && + (hash[2] == com_on_air_ids[i].prod_id_hash[2]) && + (hash[3] == com_on_air_ids[i].prod_id_hash[3]) ) + { + found = 1; + ret = i; + } + i++; + } + if (!found) + printk("com_on_air_cs: ERROR: get_card_id() " + "didn't find card, please update driver\n"); + return ret; +} + +static struct pcmcia_driver coa_driver = +{ + .owner = THIS_MODULE, + .drv = + { + .name = COA_DEVICE_NAME, + }, + .probe = com_on_air_probe, + .remove = com_on_air_remove, + + .suspend = com_on_air_suspend, + .resume = com_on_air_resume, + + .id_table = com_on_air_ids, +}; + +static int __init init_com_on_air_cs(void) +{ + int ret = 0; + printk(">>> loading " COA_DEVICE_NAME "\n"); + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + ret = pcmcia_register_driver(&coa_driver); + if (ret != CS_SUCCESS) + { + printk("couldn't pcmcia_register_driver()\n"); + goto init_out_3; + } + + ret = register_chrdev(0xDEC, COA_DEVICE_NAME, &coa_fops); + if (ret < 0) + { + printk("couldn't register_chrdev()\n"); + goto init_out_2; + } + + spin_lock_init(&dev->rx_fifo_lock); + dev->rx_fifo = kfifo_alloc(COA_FIFO_SIZE, GFP_KERNEL, + &dev->rx_fifo_lock); + if (IS_ERR(dev->rx_fifo)) + { + printk("couldn't kfifo_alloc(dev->rx_fifo)\n"); + goto init_out_1; + } + + spin_lock_init(&dev->tx_fifo_lock); + dev->tx_fifo = kfifo_alloc(COA_FIFO_SIZE, GFP_KERNEL, + &dev->tx_fifo_lock); + if (IS_ERR(dev->tx_fifo)) + { + printk("couldn't kfifo_alloc(dev->tx_fifo)\n"); + goto init_out_0; + } + + return 0; + +init_out_0: + kfifo_free(dev->rx_fifo); +init_out_1: + unregister_chrdev(0xDEC, COA_DEVICE_NAME); +init_out_2: + pcmcia_unregister_driver(&coa_driver); +init_out_3: + kfree(dev); + return ret; +} + +static void __exit exit_com_on_air_cs(void) +{ + printk("<<< unloading " COA_DEVICE_NAME "\n"); + + if (!dev) return; + + unregister_chrdev(0xDEC, COA_DEVICE_NAME); + + pcmcia_unregister_driver(&coa_driver); + + kfifo_free(dev->rx_fifo); + kfifo_free(dev->tx_fifo); + + kfree(dev); +} + +module_init(init_com_on_air_cs); +module_exit(exit_com_on_air_cs); + diff --git a/com-on-air_cs-linux/com_on_air.h b/com-on-air_cs-linux/com_on_air.h new file mode 100644 index 0000000..96e1af7 --- /dev/null +++ b/com-on-air_cs-linux/com_on_air.h @@ -0,0 +1,65 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef COM_ON_AIR_H +#define COM_ON_AIR_H + +#include +#include +#include +#include + + +struct coa_info +{ + struct pcmcia_device *p_dev; + config_info_t config; + int open; + + int irq; + int irq_count; + struct timespec irq_timestamp; + + struct pcmcia_device *links[2]; + + caddr_t membase[2]; + u_int memsize[2]; + + + /* hardware configs */ + unsigned short *sc14421_base; + unsigned int card_id; /* index into com_on_air_ids[] */ + unsigned int radio_type; + + unsigned int operation_mode; + + /* struct fp_cfg *fp_config; */ + /* struct pp_cfg *pp_config; */ + struct sniffer_cfg *sniffer_config; + + struct kfifo *rx_fifo; + spinlock_t rx_fifo_lock; + struct kfifo *tx_fifo; + spinlock_t tx_fifo_lock; +}; + + +int get_card_id(void); + +/* radio types */ +#define COA_RADIO_TYPE_II 0 +#define COA_RADIO_TYPE_III 1 +#define COA_RADIO_FREEPAD 2 + + +#endif diff --git a/com-on-air_cs-linux/com_on_air_user.h b/com-on-air_cs-linux/com_on_air_user.h new file mode 100644 index 0000000..f79edbc --- /dev/null +++ b/com-on-air_cs-linux/com_on_air_user.h @@ -0,0 +1,45 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef COM_ON_AIR_USER_H +#define COM_ON_AIR_USER_H + +/* operation modes */ +#define COA_MODEMASK 0xFF00 +#define COA_SUBMODEMASK 0x00FF + +#define COA_MODE_IDLE 0x0000 +#define COA_MODE_FP 0x0100 +#define COA_MODE_PP 0x0200 +#define COA_MODE_SNIFF 0x0300 +#define COA_MODE_JAM 0x0400 + + +#define COA_SUBMODE_SNIFF_SCANFP 0x0001 +#define COA_SUBMODE_SNIFF_SCANPP 0x0002 +#define COA_SUBMODE_SNIFF_SYNC 0x0003 + + +/* ioctl */ + +#define COA_IOCTL_MODE 0xD000 +#define COA_IOCTL_RADIO 0xD001 +#define COA_IOCTL_RX 0xD002 +#define COA_IOCTL_TX 0xD003 +#define COA_IOCTL_CHAN 0xD004 +#define COA_IOCTL_SLOT 0xD005 +#define COA_IOCTL_RSSI 0xD006 +#define COA_IOCTL_FIRMWARE 0xD007 /* request_firmware() */ +#define COA_IOCTL_SETRFPI 0xD008 + +#endif diff --git a/com-on-air_cs-linux/dect.c b/com-on-air_cs-linux/dect.c new file mode 100644 index 0000000..5a867a4 --- /dev/null +++ b/com-on-air_cs-linux/dect.c @@ -0,0 +1,318 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include "dect.h" + +#define DECT_A_TA 0xe0 +#define DECT_A_Q1 0x10 +#define DECT_A_BA 0x0e +#define DECT_A_Q2 0x01 + +#define DECT_Q_TYPE 0x80 +#define DECT_N_TYPE 0x60 +#define DECT_P_TYPE 0xe0 + +#define DECT_Q_HEAD 0xf0 + +#define DECT_Q_HEAD_SSINFO 0x00 /* Static System info */ +#define DECT_Q_HEAD_EXTRF1 0x20 /* Extended RF Carriers Part 1 */ +#define DECT_Q_HEAD_FPC 0x30 /* Fixed Part Capabilities */ +#define DECT_Q_HEAD_MULTIFN 0x60 /* Multi Frame Number */ + +#define DECT_Q_SSINFO_SLOT 0x0f + + +#define DECT_P_EXTFLAG 0x80 +#define DECT_P_HEAD 0x70 + +#define DECT_P_HEAD_ZEROLP 0x00 /* Zero Length Page */ +#define DECT_P_HEAD_SHORTLP 0x10 /* Short Length Page */ +#define DECT_P_HEAD_FULLLP 0x20 /* Full Length Page */ +#define DECT_P_HEAD_MACRES 0x30 /* MAC Resume Page */ +#define DECT_P_HEAD_NOTLAST36 0x40 /* Not the Last 36 Bits of Long Page */ +#define DECT_P_HEAD_FIRST36 0x50 /* First 36 Bit of Long Page */ +#define DECT_P_HEAD_LAST26 0x60 /* Last 36 Bit of Long Page */ +#define DECT_P_HEAD_ALLOFLP 0x70 /* All of Long Page (first and last) */ + +#define DECT_P_INFOTYPE 0xf0 + +#define DECT_P_IT_FILLBITS 0x00 /* Fill Bits */ +#define DECT_P_IT_BFCIRCUIT 0x10 /* Blind Full Slot Information for \ + Circuit Mode Service */ +#define DECT_P_IT_OTHERBEAR 0x20 /* Other Bearer */ +#define DECT_P_IT_RECOTHERBEAR 0x30 /* Recommended Other Bearer */ +#define DECT_P_IT_GOODRFPBEAR 0x40 /* Good RFP Bearer */ +#define DECT_P_IT_DUMMYCLPOS 0x50 /* Dummy or C/L Bearer Position */ +#define DECT_P_IT_EXTMODULTYPE 0x60 /* Extended Modulation Type */ +#define DECT_P_IT_ESCAPE 0x70 /* Escape */ +#define DECT_P_IT_DUMMYCLBEARM 0x80 /* Dummy or C/L Bearer Marker */ +#define DECT_P_IT_REPLACEINFO 0x90 /* Bearer Handover/Replacement \ + Information */ + +#define DECT_P_IT_BEARERPOS_SN 0x0f /* Slot Number */ +#define DECT_P_IT_BEARERPOS_SP 0xc0 /* Start Position */ +#define DECT_P_IT_BEARERPOS_CN 0x3f /* Channel */ + +int dect_is_RFPI_Packet(unsigned char *packet) +{ + if ((packet[5] & DECT_A_TA) == DECT_N_TYPE) + return 1; + + return 0; +} + +int dect_compare_RFPI(unsigned char *packet, unsigned char* RFPI) +{ + if ((packet[5] & DECT_A_TA) == DECT_N_TYPE) + { + if (!memcmp(&packet[6], RFPI, 5)) + return 1; + } + + return 0; +} + +int dect_get_slot(unsigned char *packet) +{ + int slot = -1; + + if ((packet[5] & DECT_A_TA) == DECT_Q_TYPE) + { + if ((packet[6] & DECT_Q_HEAD) == DECT_Q_HEAD_SSINFO) + { + slot = packet[6] & DECT_Q_SSINFO_SLOT; + } + } + + return slot; +} + +int dect_is_multiframe_number(unsigned char *packet) +{ + if ((packet[5] & DECT_A_TA) == DECT_Q_TYPE) + { + /*printk("bl"); */ + if ((packet[6] & DECT_Q_HEAD) == DECT_Q_HEAD_MULTIFN) + { + /*printk("aa\n"); */ + return 1; + } + } + + return 0; +} + +int dect_is_fp_packet(unsigned char *packet) +{ + if ( (packet[3] == 0xe9) && (packet[4] == 0x8a) ) + return 1; + + return 0; +} + +int dect_is_pp_packet(unsigned char *packet) +{ + if ( (packet[3] == 0x16) && (packet[4] == 0x75) ) + return 1; + + return 0; +} + + +int dect_update_slottable(struct dect_slot_info *slottable, int slot, unsigned char *packet) +{ + if (slottable[slot].type == DECT_SLOTTYPE_SCAN) + { + printk("received packet on scanslot %u on carrier %u\n", slot, slottable[slot].channel); + slottable[slot].type = DECT_SLOTTYPE_CARRIER; + if (slottable[slot].channel == 0) + slottable[slot].channel = 9; + else + slottable[slot].channel--; + slottable[slot].errcnt = 0; + slottable[slot].update = 1; + + if (slot > 12) + { + slottable[slot-12].type = DECT_SLOTTYPE_CARRIER; + if (slottable[slot-12].channel == 0) + slottable[slot-12].channel = 9; + else + slottable[slot-12].channel--; + slottable[slot-12].errcnt = 0; + slottable[slot].update = 1; + } + else + { + slottable[slot+12].type = DECT_SLOTTYPE_CARRIER; + if (slottable[slot+12].channel == 0) + slottable[slot+12].channel = 9; + else + slottable[slot+12].channel--; + slottable[slot+12].errcnt = 0; + slottable[slot].update = 1; + } + } + + if (dect_is_fp_packet(packet)) + { + + switch(packet[5] & DECT_A_TA) + { + case DECT_P_TYPE: + if ( ( (packet[6] & DECT_P_HEAD) == + DECT_P_HEAD_ZEROLP) || + ( (packet[6] & DECT_P_HEAD) == + DECT_P_HEAD_SHORTLP) ) + { + switch((packet[9] & DECT_P_INFOTYPE)) + { + case DECT_P_IT_OTHERBEAR: + { + int newslot = (packet[9] & DECT_P_IT_BEARERPOS_SN) % 12; + slottable[newslot].active = 1; + slottable[newslot].channel = packet[10] & DECT_P_IT_BEARERPOS_CN; + slottable[newslot].type = DECT_SLOTTYPE_CARRIER; + slottable[newslot].errcnt = 0; + slottable[newslot].update = 1; + + slottable[newslot+12].active = 1; + slottable[newslot+12].channel = packet[10] & DECT_P_IT_BEARERPOS_CN; + slottable[newslot+12].type = DECT_SLOTTYPE_CARRIER; + slottable[newslot+12].errcnt = 0; + slottable[newslot+12].update = 1; + + /*printk("\n\nstation switching to slot %u channel %u\n\n",newslot, packet[10] & DECT_P_IT_BEARERPOS_CN); */ + return 1; + } + + case DECT_P_IT_BFCIRCUIT: /* set scanning slots */ + { + int i, x, ret = 0; + unsigned int slots = (((unsigned int)(packet[9] & ~DECT_P_INFOTYPE)) << 8) | packet[10]; + + for (i=0; i<12; i++) + { + x = (slots & 0x800 ? 1:0); + slots <<= 1; + + if (x && (!slottable[i].active)) + { + printk("scanning on slot %u\n", i); + slottable[i].active = 1; + slottable[i].channel = 0; /* channel unknown at this position */ + slottable[i].type = DECT_SLOTTYPE_SCAN; + slottable[i].errcnt = 0; + slottable[i].update = 1; + ret = 1; + } + + if (x && (!slottable[i+12].active)) + { + printk("scanning on slot %u\n", i + 12); + slottable[i+12].active = 1; + slottable[i+12].channel = 0; /* channel unknown at this position */ + slottable[i+12].type = DECT_SLOTTYPE_SCAN; + slottable[i+12].errcnt = 0; + slottable[i+12].update = 1; + ret = 1; + } + } + + return ret; + } + } + } + + break; + case DECT_Q_TYPE: + if ((packet[6] & DECT_Q_HEAD) == DECT_Q_HEAD_SSINFO) + { + uint8_t pscan = packet[10]; + int i, ret = 0; + + for (i=0; i<24; i++) + { + if (slottable[i].active) + { + if (slottable[i].type == DECT_SLOTTYPE_SCAN) + { +/* if (pscan == 0) + pscan = 9; + else + pscan--; +*/ + slottable[i].channel = pscan; + slottable[i].update = 1; + ret = 1; + } + } + } + + return ret; + } + + break; + + } + + } + + return 0; +} + +int dect_receive_error(struct dect_slot_info *slottable, int slot) +{ + slottable[slot].errcnt++; + + if (slottable[slot].type != DECT_SLOTTYPE_SCAN) + { + if (slottable[slot].errcnt > 32) + { + slottable[slot].active = 0; + slottable[slot].update = 1; + + printk("slot %u on channel %u died\n", slot, slottable[slot].channel); + + return 1; + } + } + + return 0; +} + +int dect_update_scanchannels(struct dect_slot_info *slottable) +{ + int i, ret = 0; + + for (i=0; i<24; i++) /* Increment primary scan channel */ + { + if (slottable[i].active) + { + if (slottable[i].type == DECT_SLOTTYPE_SCAN) + { + slottable[i].channel++; + if (slottable[i].channel > 9) + slottable[i].channel = 0; + + slottable[i].update = 1; + + ret = 1; + + /*printk("slot %u will now scan on carrier %u\n", i, slottable[i].channel); */ + } + } + } + + return ret; +} diff --git a/com-on-air_cs-linux/dect.h b/com-on-air_cs-linux/dect.h new file mode 100644 index 0000000..4706560 --- /dev/null +++ b/com-on-air_cs-linux/dect.h @@ -0,0 +1,42 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef DECT_H +#define DECT_H + +#include +#include + +#define DECT_SLOTTYPE_CARRIER 0 +#define DECT_SLOTTYPE_SCAN 1 + +struct dect_slot_info +{ + uint8_t active; + uint8_t channel; + uint8_t type; + uint8_t errcnt; + uint8_t update; +}; + + +int dect_is_RFPI_Packet(unsigned char *packet); +int dect_compare_RFPI(unsigned char *packet, unsigned char* RFPI); +int dect_get_slot(unsigned char *packet); +int dect_is_multiframe_number(unsigned char *packet); +int dect_is_fp_packet(unsigned char *packet); +int dect_is_pp_packet(unsigned char *packet); +int dect_update_slottable(struct dect_slot_info *slottable, int slot, unsigned char *packet); +int dect_receive_error(struct dect_slot_info *slottable, int slot); +int dect_update_scanchannels(struct dect_slot_info *slottable); +#endif diff --git a/com-on-air_cs-linux/dip_opcodes.h b/com-on-air_cs-linux/dip_opcodes.h new file mode 100644 index 0000000..e4ec07d --- /dev/null +++ b/com-on-air_cs-linux/dip_opcodes.h @@ -0,0 +1,161 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef DIP_OPCODE_H +#define DIP_OPCODE_H + + +#define BR 0x01 +#define JMP 0x02 +#define JMP1 0x03 +#define RTN 0x04 +#define BK_A1 0x05 +#define WNTM1 0x06 +#define WNTP1 0x07 +#define WNT 0x08 +#define WT 0x09 +#define RFDIS 0x0a +#define RFEN 0x0b +#define LD_PTR 0x0c +#define SLOTZERO 0x0d +#define BK_A 0x0e +#define BK_C 0x0f + + +#define B_RST 0x20 +#define B_ST2 0x21 +#define B_XT 0x24 +#define B_BT2 0x25 +#define B_BTFU 0x25 +#define B_XOFF 0x26 +#define B_ON 0x27 +#define B_XON 0x27 +#define UNLCK 0x28 +#define B_SR 0x29 +#define B_XR 0x2b +#define EN_SL_ADJ 0x2c +#define B_BR2 0x2d +#define B_BRFU 0x2d +#define B_RINV 0x2e +#define B_RON 0x2f + + +#define B_ST 0x31 +#define B_TX 0x31 +#define B_AT 0x32 +#define B_RC 0x33 +#define B_BT 0x34 +#define B_BTFP 0x35 +#define B_BTP 0x35 +#define B_AT2 0x37 +#define B_WRS 0x39 +#define B_AR 0x3a +#define B_BR 0x3c +#define B_BRP 0x3d +#define B_BRFP 0x3d +#define B_AR2 0x3f + + +#define D_RST 0x40 +#define D_ON 0x42 +#define D_OFF 0x43 +#define D_PREP 0x44 +#define WSC 0x48 + + +#define D_LDK 0x50 +#define D_LDS 0x57 +#define D_WRS 0x5f + + +#define U_PSC 0x60 +#define U_INT0 0x61 +#define RCK_INT 0x62 +#define RCK_EXT 0x63 +#define B_WB_OFF 0x64 +#define B_WB_ON 0x65 +#define CLK1 0x66 +#define CLK3 0x67 +#define U_CK8 0x68 +#define U_CK4 0x69 +#define U_CK2 0x6a +#define U_INT1 0x6b +#define U_CK1 0x6c +#define U_INT2 0x6d +#define U_INT3 0x6f + + +#define A_RCV0 0x80 +#define A_RCV36 0x82 +#define A_RCV30 0x83 +#define A_RCV24 0x84 +#define A_RCV18 0x85 +#define A_RCV12 0x86 +#define A_RCV6 0x87 +#define A_RCV33 0x8a +#define A_RCV27 0x8b +#define A_RCV21 0x8c +#define A_RCV15 0x8d +#define A_RCV9 0x8e +#define A_RCV3 0x8f + + +#define MEN3N 0xa2 +#define MEN3 0xa3 +#define MEN1N 0xa4 +#define MEN1 0xa5 +#define MEN2N 0xa6 +#define MEN2 0xa7 +#define M_RD 0xa8 +#define M_RST 0xa9 + + +#define M_WRS 0xb8 +#define M_WR 0xb9 + + +#define A_RST 0xc0 +#define A_MUTE 0xc1 +#define A_STOFF 0xc2 +#define A_ALAW 0xc3 +#define A_DT 0xc4 +#define A_NORM 0xc5 +#define A_LDR 0xc6 +#define A_LDW 0xc7 +#define A_LIN 0xc8 +#define A_MTOFF 0xc9 +#define A_MUTE1 0xca +#define A_MTOFF1 0xcb +#define A_STON 0xcc +#define A_DT1 0xcd +#define A_LDR1 0xce +#define A_LDW1 0xcf + + +#define A_STRN 0xe0 +#define P_LD 0xe8 +#define P_EN 0xe9 +#define P_SC 0xea +#define A_RST1 0xeb +#define P_LDL 0xec +#define P_LDH 0xed +#define C_ON 0xee +#define C_OFF 0xef + + +#define C_LD 0xfa + + + +#endif + diff --git a/com-on-air_cs-linux/firmware/.h b/com-on-air_cs-linux/firmware/.h new file mode 100644 index 0000000..ab9cd16 --- /dev/null +++ b/com-on-air_cs-linux/firmware/.h @@ -0,0 +1 @@ +extern unsigned char _fw[509]; diff --git a/com-on-air_cs-linux/firmware/Makefile b/com-on-air_cs-linux/firmware/Makefile new file mode 100644 index 0000000..cd8a096 --- /dev/null +++ b/com-on-air_cs-linux/firmware/Makefile @@ -0,0 +1,37 @@ +CFLAGS=-Wall -O2 + +FW=sc14421_firmware + +FW1=sc14421_II_sniff_scan +FW2=sc14421_II_sniff_sync + +ALL_FW=$(FW1) $(FW2) + +BIN2C=./bin2c + +all: ../$(FW).h ../$(FW).c + +../$(FW).h: $(FW1).h $(FW2).h + cat sc14421_header.h $^ sc14421_footer.h > $@ + +../$(FW).c: $(FW1).c $(FW2).c + cat $^ > $@ + +$(FW1).c $(FW2).c: $(FW1).bin $(FW2).bin $(BIN2C) + $(BIN2C) $(@:.c=.bin) $(@:.c=)_fw > $@ + +%.bin: %.p + p2bin $^ $@ -r 0-507 + +%.p: %.asm + asl $^ + +$(FW1).h $(FW2).h: + echo "extern unsigned char $(@:.h=)_fw[509];" > $@ + +clean: + rm -f ../$(FW).h ../$(FW).c $(BIN2C) + rm -f $(foreach f,$(ALL_FW),$f.c) + rm -f $(foreach f,$(ALL_FW),$f.h) + rm -f $(foreach f,$(ALL_FW),$f.bin) + diff --git a/com-on-air_cs-linux/firmware/bin2c.c b/com-on-air_cs-linux/firmware/bin2c.c new file mode 100644 index 0000000..89afecd --- /dev/null +++ b/com-on-air_cs-linux/firmware/bin2c.c @@ -0,0 +1,55 @@ +#include + #include + #include + #include + #include + #include + #include + #include + #include + +#define HEADER_FMT \ + "\n\n" \ + "/* automatically generated file\n" \ + " * DO NOT EDIT\n" \ + " * edit firmware/filename.asm instead */\n" \ + "\n" \ + "unsigned char %s[] = {\n" + +#define FOOTER "};\n" + +int main(int argc, char *argv[]) +{ + if(argc<3) + { + printf("usage: bin2c bin-file varname > c-file\n"); + exit(1); + } + + int f = open(argv[1], O_RDONLY); + if(f<0) + { + printf("cant open(\"%s\"): %s\n", argv[1], strerror(errno)); + exit(1); + } + + printf(HEADER_FMT, argv[2]); + + uint32_t wordcount = 0; + uint16_t w; + while (2 == read(f, &w, 2)) + { + if (!wordcount) + printf("\t"); + else + if (!(wordcount % 4)) + printf(",\n\t"); + else + printf(", "); + printf("0x%.2x, 0x%.2x", (w&0xff00)>>8, w&0xff); + wordcount++; + } + printf(FOOTER); + close(f); + return 0; +} diff --git a/com-on-air_cs-linux/firmware/sc14421_II_sniff_scan.asm b/com-on-air_cs-linux/firmware/sc14421_II_sniff_scan.asm new file mode 100644 index 0000000..0c0aab7 --- /dev/null +++ b/com-on-air_cs-linux/firmware/sc14421_II_sniff_scan.asm @@ -0,0 +1,110 @@ + CPU SC14421 + + ORG 0 + BR Start + + +PB_LED EQU 0x80 +PB_RX_ON EQU 0x40 +PB_TX_ON EQU 0x10 +PB_RADIOPOWER EQU 0x04 +PB_DCTHRESHOLD EQU 0x02 +PB_RSSI EQU 0x01 + +;------------------------------------------------------------- + +Start: B_RST + BK_C 0x00 + C_LD 0x10 + WT 10 + B_RC 0x00 + WT 8 + B_RST + C_ON + WT 10 + P_EN + P_LD PB_RADIOPOWER + RCK_INT + RFEN +;------------------------------------------------------------- + + BK_C 0x20 + JMP RFInit +TryAgain: JMP label_B1 + WT 250 + P_SC 0x20 + P_LDH PB_RX_ON|PB_DCTHRESHOLD + UNLCK + WT 64 + B_XOFF + B_SR + WNT 20 + JMP1 SFieldFound + BR TryAgain +;------------------------------------------------------------- + +SFieldFound: WNT 23 + P_SC 0x00 + JMP ReceiveSlot + U_INT0 + BR TryAgain +;------------------------------------------------------------- + +ReceiveSlot: JMP label_B1 + JMP RecvPP + WT 1 + B_BRFU 0x0e + WT 255 + WT 73 + P_LDH PB_RSSI + P_LDL PB_RX_ON + B_WRS 0x00 + WT 6 + B_RST + P_LDL PB_RX_ON|PB_TX_ON + WT 5 + RTN +;------------------------------------------------------------- + +RecvPP: P_LDH PB_RX_ON + P_LDL PB_RSSI + WT 34 + WNT 1 + B_XON + P_LDH PB_DCTHRESHOLD + WT 5 + B_SR + EN_SL_ADJ + WT 12 + P_LDL PB_DCTHRESHOLD + WT 33 + B_AR2 0x06 + WT 61 + RTN +;------------------------------------------------------------- + +RFInit: RFEN + MEN1N + WT 2 + M_WR 0x4A + WT 25 + M_RST + MEN1 + MEN1N + M_WR 0x4D + WT 10 + M_RST + MEN1 + RTN +;------------------------------------------------------------- + +label_B1: B_RST + B_RC 0x58 + WT 8 + MEN2 + WT 182 + MEN2N + WT 16 + RTN +;------------------------------------------------------------- + diff --git a/com-on-air_cs-linux/firmware/sc14421_II_sniff_sync.asm b/com-on-air_cs-linux/firmware/sc14421_II_sniff_sync.asm new file mode 100644 index 0000000..49c23fa --- /dev/null +++ b/com-on-air_cs-linux/firmware/sc14421_II_sniff_sync.asm @@ -0,0 +1,298 @@ + CPU SC14421 + + ORG 0 + BR Start + + +PB_LED EQU 0x80 +PB_RX_ON EQU 0x40 +PB_TX_ON EQU 0x10 +PB_RADIOPOWER EQU 0x04 +PB_DCTHRESHOLD EQU 0x02 +PB_RSSI EQU 0x01 + +;------------------------------------------------------------- + +Start: BR InitDIP +;------------------------------------------------------------- + +SlotTable: SLOTZERO +JP0: BK_C 0x20 +PP0: WNT 2 +JP2: BK_C 0x30 +PP2: WNT 2 +JP4: BK_C 0x40 +PP4: WNT 2 +JP6: BK_C 0x50 +PP6: WNT 2 +JP8: BK_C 0x60 +PP8: WNT 2 +JP10: BK_C 0x70 +PP10: WNT 2 + U_INT0 +JP12: BK_C 0x80 +PP12: WNT 2 +JP14: BK_C 0x90 +PP14: WNT 2 +JP16: BK_C 0xA0 +PP16: WNT 2 +JP18: BK_C 0xB0 +PP18: WNT 2 +JP20: BK_C 0xC0 +PP20: WNT 2 +JP22: BK_C 0xD0 +PP22: WNT 2 + U_INT3 + P_LDL 0x80 + BR SlotTable +;------------------------------------------------------------- + +label_28: JMP RFInit + JMP label_B1 + BR label_2D +;------------------------------------------------------------- + + JMP RFInit + JMP label_B3 +label_2D: JMP RecvPP + WT 1 + B_BRFU 0x0E + JMP label_6B + BR label_51 +;------------------------------------------------------------- + + JMP RFInit + JMP label_B1 + BR label_37 +;------------------------------------------------------------- + + JMP RFInit + JMP label_B3 +label_37: JMP RecvPP + BR label_92 +;------------------------------------------------------------- + + JMP RFInit + JMP label_B1 + BR label_3E +;------------------------------------------------------------- + + JMP RFInit + JMP label_B3 +label_3E: JMP label_70 + WT 1 + B_BTFU 0x0E + JMP label_7C + BR label_54 +;------------------------------------------------------------- + + JMP RFInit + JMP label_B3 + JMP label_70 + WT 1 + B_BT 0x0E + JMP label_7F + BR label_53 +;------------------------------------------------------------- + + JMP RFInit + JMP label_B1 + BR label_4F +;------------------------------------------------------------- + + JMP RFInit + JMP label_B3 +label_4F: JMP label_70 + BR label_9B +;------------------------------------------------------------- + +label_51: B_WRS 0x00 + WT 6 +label_53: B_RST +label_54: P_LDL 0x50 + WT 5 + WNT 1 +label_57: RTN +;------------------------------------------------------------- + +label_58: B_RST + P_LDL 0x50 + BR label_57 +;------------------------------------------------------------- + +RecvPP: P_LDH 0x40 + P_LDL PB_RSSI + WT 25 + WNT 1 + WT 9 + B_XON + P_LDH 0x02 + WT 5 + B_SR + EN_SL_ADJ + WT 12 + P_LDL 0x02 + WT 33 + B_AR2 0x06 + WT 61 + RTN +;------------------------------------------------------------- + +label_6B: WT 249 + WT 79 +label_6D: P_LDH PB_RSSI + P_LDL 0x40 + RTN +;------------------------------------------------------------- + +label_70: P_LDH 0x00 + WT 40 + B_RST + B_RC 0x50 + WNT 1 + B_ST 0x00 + WT 1 + P_LDH 0x10 + WT 37 + B_AT2 0x06 + WT 61 + RTN +;------------------------------------------------------------- + +label_7C: WT 249 + WT 84 + B_RST +label_7F: P_LDL 0x10 + WT 8 + P_LDL 0x00 + RTN +;------------------------------------------------------------- + +label_83: B_XON + WT 15 + B_XOFF + WT 61 + RTN +;------------------------------------------------------------- + +label_88: WT 61 + JMP label_83 + JMP label_83 + JMP label_83 + JMP label_83 + JMP label_83 + WT 1 + B_XON + WT 11 + RTN +;------------------------------------------------------------- + +label_92: B_BR 0x0E + JMP label_88 + WT 3 + B_XR + WT 6 + JMP label_6D + B_WRS 0x00 + WT 6 + BR label_58 +;------------------------------------------------------------- + +label_9B: B_BT 0x0E + WT 3 + JMP label_88 + B_XT + WT 13 + B_RST + JMP label_7F + BR label_58 +;------------------------------------------------------------- + +RFInit: RFEN + MEN1N + WT 1 + WT 1 + M_WR 0x4A + WT 25 + M_RST + MEN1 + MEN1N + M_WR 0x4D + WT 10 + M_RST + MEN1 + RTN +;------------------------------------------------------------- + +label_B1: P_LDL 0x20 + BR label_B5 +;------------------------------------------------------------- + +label_B3: P_LDH 0x20 + BR label_B5 +;------------------------------------------------------------- + +label_B5: B_RST + B_RC 0x58 + WT 8 + MEN2 + WT 118 + WT 64 + MEN2N + P_LDH 0x00 + WT 16 + RTN +;------------------------------------------------------------- + +PPSync: BK_C 0x20 +label_C0: JMP RFInit + JMP label_B1 + WT 250 + P_SC 0x20 + P_LDH PB_RX_ON|PB_DCTHRESHOLD + UNLCK + WT 64 + B_XOFF + B_SR + WNT 20 + JMP1 SFieldFound + B_RST + U_INT1 + WNT 23 + BR label_C0 +;------------------------------------------------------------- + +SFieldFound: WNT 23 + P_SC 0x00 +label_D1: JMP label_28 + U_INT0 + WNT 22 +label_D4: BR label_C0 +;------------------------------------------------------------- + +InitDIP: B_RST + BK_C 0x00 + C_LD 0x10 + WT 10 + B_RC 0x00 + WT 8 + B_RST + BK_A 0x00 + A_LDR 0x8C + A_LDW 0xB4 + BK_A1 0x00 + A_LDR1 0x0C + A_LDW1 0x34 + C_ON + A_NORM + WT 10 + P_EN + P_LD 0x04 + RCK_INT + RFEN + BR PPSync +;------------------------------------------------------------- + + SHARED PP0,PP2,PP4,PP6,PP8,PP10,PP12,PP14,PP16,PP18,PP20,PP22 + SHARED JP0,JP2,JP4,JP6,JP8,JP10,JP12,JP14,JP16,JP18,JP20,JP22 + SHARED label_D1,label_D4,label_28 diff --git a/com-on-air_cs-linux/firmware/sc14421_footer.h b/com-on-air_cs-linux/firmware/sc14421_footer.h new file mode 100644 index 0000000..ddd5dae --- /dev/null +++ b/com-on-air_cs-linux/firmware/sc14421_footer.h @@ -0,0 +1,2 @@ + +#endif diff --git a/com-on-air_cs-linux/firmware/sc14421_header.h b/com-on-air_cs-linux/firmware/sc14421_header.h new file mode 100644 index 0000000..60ca6b6 --- /dev/null +++ b/com-on-air_cs-linux/firmware/sc14421_header.h @@ -0,0 +1,3 @@ +#ifndef SC14421_FIRMWARE_H +#define SC14421_FIRMWARE_H + diff --git a/com-on-air_cs-linux/sc14421.c b/com-on-air_cs-linux/sc14421.c new file mode 100644 index 0000000..b7f7ad2 --- /dev/null +++ b/com-on-air_cs-linux/sc14421.c @@ -0,0 +1,146 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include +#include + +#include "sc14421.h" +#include "dip_opcodes.h" + +static u_int deviceConfigBase = 0; + +void set_device_configbase(u_int configBase) +{ + deviceConfigBase = configBase; +} + +void wait_4_IO_cycles() +{ + if (!deviceConfigBase) { + printk("error: config base not set!\n"); + return; + } + inb_p(deviceConfigBase); + inb_p(deviceConfigBase); + inb_p(deviceConfigBase); + inb_p(deviceConfigBase); +} + +void to_dip(uint16_t *dst, unsigned char *src, int length) +{ + int i; + for (i=0; i + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef SC14421_H +#define SC14421_H + +#include + +#define SC14421_DIPSTOPPED 0x80 +#define SC14421_RAMBANK0 0x00 +#define SC14421_RAMBANK1 0x04 +#define SC14421_RAMBANK2 0x08 +#define SC14421_RAMBANK3 0x0c +#define SC14421_RAMBANK4 0x10 +#define SC14421_RAMBANK5 0x14 +#define SC14421_RAMBANK6 0x18 +#define SC14421_RAMBANK7 0x1c +#define SC14421_CODEBANK 0x20 + +#if defined(__LITTLE_ENDIAN) +# define SC14421_READ(offset) sc14421_base[(offset)] +# define SC14421_WRITE(offset, value) { sc14421_base[(offset)] = (value); } +#elif defined(__BIG_ENDIAN) +# define SC14421_READ(offset) swab16(sc14421_base[(offset)]) +# define SC14421_WRITE(offset, value) { sc14421_base[(offset)] = swab16(value); } +#else +# error "could not determine endianness" +#endif + +void set_device_configbase(u_int); +void wait_4_IO_cycles(void); +void to_dip(unsigned short *dst, unsigned char *src, int length); +void from_dip(unsigned char *dst, volatile uint16_t *src, int length); +void SC14421_switch_to_bank(volatile uint16_t *sc14421_base, unsigned char bank); +void SC14421_stop_dip(volatile uint16_t *sc14421_base); +void SC14421_write_cmd(volatile uint16_t *sc14421_base, int label, unsigned char opcode, unsigned char operand); +unsigned char SC14421_clear_interrupt(volatile uint16_t *sc14421_base); +int SC14421_check_RAM(volatile uint16_t *sc14421_base); + +#endif diff --git a/com-on-air_cs-linux/sc14421_firmware.c b/com-on-air_cs-linux/sc14421_firmware.c new file mode 100644 index 0000000..8216b5e --- /dev/null +++ b/com-on-air_cs-linux/sc14421_firmware.c @@ -0,0 +1,142 @@ + + +/* automatically generated file + * DO NOT EDIT + * edit firmware/filename.asm instead */ + +unsigned char sc14421_II_sniff_scan_fw[] = { + 0x01, 0x01, 0x20, 0x00, 0x0f, 0x00, 0xfa, 0x10, + 0x09, 0x0a, 0x33, 0x00, 0x09, 0x08, 0x20, 0x00, + 0xee, 0x00, 0x09, 0x0a, 0xe9, 0x00, 0xe8, 0x04, + 0x62, 0x00, 0x0b, 0x00, 0x0f, 0x20, 0x02, 0x3d, + 0x02, 0x4a, 0x09, 0xfa, 0xea, 0x20, 0xed, 0x42, + 0x28, 0x00, 0x09, 0x40, 0x26, 0x00, 0x29, 0x00, + 0x08, 0x14, 0x03, 0x1b, 0x01, 0x10, 0x08, 0x17, + 0xea, 0x00, 0x02, 0x20, 0x61, 0x00, 0x01, 0x10, + 0x02, 0x4a, 0x02, 0x2e, 0x09, 0x01, 0x2d, 0x0e, + 0x09, 0xff, 0x09, 0x49, 0xed, 0x01, 0xec, 0x40, + 0x39, 0x00, 0x09, 0x06, 0x20, 0x00, 0xec, 0x50, + 0x09, 0x05, 0x04, 0x00, 0xed, 0x40, 0xec, 0x01, + 0x09, 0x22, 0x08, 0x01, 0x27, 0x00, 0xed, 0x02, + 0x09, 0x05, 0x29, 0x00, 0x2c, 0x00, 0x09, 0x0c, + 0xec, 0x02, 0x09, 0x21, 0x3f, 0x06, 0x09, 0x3d, + 0x04, 0x00, 0x0b, 0x00, 0xa4, 0x00, 0x09, 0x02, + 0xb9, 0x4a, 0x09, 0x19, 0xa9, 0x00, 0xa5, 0x00, + 0xa4, 0x00, 0xb9, 0x4d, 0x09, 0x0a, 0xa9, 0x00, + 0xa5, 0x00, 0x04, 0x00, 0x20, 0x00, 0x33, 0x58, + 0x09, 0x08, 0xa7, 0x00, 0x09, 0xb6, 0xa6, 0x00, + 0x09, 0x10, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}; + + +/* automatically generated file + * DO NOT EDIT + * edit firmware/filename.asm instead */ + +unsigned char sc14421_II_sniff_sync_fw[] = { + 0x01, 0x01, 0x01, 0xcc, 0x0d, 0x00, 0x0f, 0x20, + 0x08, 0x02, 0x0f, 0x30, 0x08, 0x02, 0x0f, 0x40, + 0x08, 0x02, 0x0f, 0x50, 0x08, 0x02, 0x0f, 0x60, + 0x08, 0x02, 0x0f, 0x70, 0x08, 0x02, 0x61, 0x00, + 0x0f, 0x80, 0x08, 0x02, 0x0f, 0x90, 0x08, 0x02, + 0x0f, 0xa0, 0x08, 0x02, 0x0f, 0xb0, 0x08, 0x02, + 0x0f, 0xc0, 0x08, 0x02, 0x0f, 0xd0, 0x08, 0x02, + 0x6f, 0x00, 0xec, 0x80, 0x01, 0x02, 0x02, 0x9a, + 0x02, 0xa8, 0x01, 0x24, 0x02, 0x9a, 0x02, 0xaa, + 0x02, 0x52, 0x09, 0x01, 0x2d, 0x0e, 0x02, 0x62, + 0x01, 0x48, 0x02, 0x9a, 0x02, 0xa8, 0x01, 0x2e, + 0x02, 0x9a, 0x02, 0xaa, 0x02, 0x52, 0x01, 0x89, + 0x02, 0x9a, 0x02, 0xa8, 0x01, 0x35, 0x02, 0x9a, + 0x02, 0xaa, 0x02, 0x67, 0x09, 0x01, 0x25, 0x0e, + 0x02, 0x73, 0x01, 0x4b, 0x02, 0x9a, 0x02, 0xaa, + 0x02, 0x67, 0x09, 0x01, 0x34, 0x0e, 0x02, 0x76, + 0x01, 0x4a, 0x02, 0x9a, 0x02, 0xa8, 0x01, 0x46, + 0x02, 0x9a, 0x02, 0xaa, 0x02, 0x67, 0x01, 0x92, + 0x39, 0x00, 0x09, 0x06, 0x20, 0x00, 0xec, 0x50, + 0x09, 0x05, 0x08, 0x01, 0x04, 0x00, 0x20, 0x00, + 0xec, 0x50, 0x01, 0x4e, 0xed, 0x40, 0xec, 0x01, + 0x09, 0x19, 0x08, 0x01, 0x09, 0x09, 0x27, 0x00, + 0xed, 0x02, 0x09, 0x05, 0x29, 0x00, 0x2c, 0x00, + 0x09, 0x0c, 0xec, 0x02, 0x09, 0x21, 0x3f, 0x06, + 0x09, 0x3d, 0x04, 0x00, 0x09, 0xf9, 0x09, 0x4f, + 0xed, 0x01, 0xec, 0x40, 0x04, 0x00, 0xed, 0x00, + 0x09, 0x28, 0x20, 0x00, 0x33, 0x50, 0x08, 0x01, + 0x31, 0x00, 0x09, 0x01, 0xed, 0x10, 0x09, 0x25, + 0x37, 0x06, 0x09, 0x3d, 0x04, 0x00, 0x09, 0xf9, + 0x09, 0x54, 0x20, 0x00, 0xec, 0x10, 0x09, 0x08, + 0xec, 0x00, 0x04, 0x00, 0x27, 0x00, 0x09, 0x0f, + 0x26, 0x00, 0x09, 0x3d, 0x04, 0x00, 0x09, 0x3d, + 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, + 0x02, 0x7a, 0x09, 0x01, 0x27, 0x00, 0x09, 0x0b, + 0x04, 0x00, 0x3c, 0x0e, 0x02, 0x7f, 0x09, 0x03, + 0x2b, 0x00, 0x09, 0x06, 0x02, 0x64, 0x39, 0x00, + 0x09, 0x06, 0x01, 0x4f, 0x34, 0x0e, 0x09, 0x03, + 0x02, 0x7f, 0x24, 0x00, 0x09, 0x0d, 0x20, 0x00, + 0x02, 0x76, 0x01, 0x4f, 0x0b, 0x00, 0xa4, 0x00, + 0x09, 0x01, 0x09, 0x01, 0xb9, 0x4a, 0x09, 0x19, + 0xa9, 0x00, 0xa5, 0x00, 0xa4, 0x00, 0xb9, 0x4d, + 0x09, 0x0a, 0xa9, 0x00, 0xa5, 0x00, 0x04, 0x00, + 0xec, 0x20, 0x01, 0xac, 0xed, 0x20, 0x01, 0xac, + 0x20, 0x00, 0x33, 0x58, 0x09, 0x08, 0xa7, 0x00, + 0x09, 0x76, 0x09, 0x40, 0xa6, 0x00, 0xed, 0x00, + 0x09, 0x10, 0x04, 0x00, 0x0f, 0x20, 0x02, 0x9a, + 0x02, 0xa8, 0x09, 0xfa, 0xea, 0x20, 0xed, 0x42, + 0x28, 0x00, 0x09, 0x40, 0x26, 0x00, 0x29, 0x00, + 0x08, 0x14, 0x03, 0xc6, 0x20, 0x00, 0x6b, 0x00, + 0x08, 0x17, 0x01, 0xb7, 0x08, 0x17, 0xea, 0x00, + 0x02, 0x1f, 0x61, 0x00, 0x08, 0x16, 0x01, 0xb7, + 0x20, 0x00, 0x0f, 0x00, 0xfa, 0x10, 0x09, 0x0a, + 0x33, 0x00, 0x09, 0x08, 0x20, 0x00, 0x0e, 0x00, + 0xc6, 0x8c, 0xc7, 0xb4, 0x05, 0x00, 0xce, 0x0c, + 0xcf, 0x34, 0xee, 0x00, 0xc5, 0x00, 0x09, 0x0a, + 0xe9, 0x00, 0xe8, 0x04, 0x62, 0x00, 0x0b, 0x00, + 0x01, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}; diff --git a/com-on-air_cs-linux/sc14421_firmware.h b/com-on-air_cs-linux/sc14421_firmware.h new file mode 100644 index 0000000..5533217 --- /dev/null +++ b/com-on-air_cs-linux/sc14421_firmware.h @@ -0,0 +1,7 @@ +#ifndef SC14421_FIRMWARE_H +#define SC14421_FIRMWARE_H + +extern unsigned char sc14421_II_sniff_scan_fw[509]; +extern unsigned char sc14421_II_sniff_sync_fw[509]; + +#endif diff --git a/com-on-air_cs-linux/sc14421_sniffer.c b/com-on-air_cs-linux/sc14421_sniffer.c new file mode 100644 index 0000000..adbdd7b --- /dev/null +++ b/com-on-air_cs-linux/sc14421_sniffer.c @@ -0,0 +1,828 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include + +#include "sc14421.h" +#include "dip_opcodes.h" +#include "com_on_air.h" +#include "sc14421_sniffer.h" +#include "sc14421_firmware.h" +#include "dect.h" + + +/* dip config register control */ +unsigned char scan_init1[] = {0x27,0x00,0xff,0x00,0x5f,0x04,0x00}; +unsigned char scan_init2[] = {0xc2,0x05,0x00,0x03,0x00,0x00}; + +/* hf register type II card */ +unsigned char scan_II_init3[] = {0x54,0x80,0x09/* patch */,0xa0,0x00,0x00}; +/* hf register type III card */ +unsigned char scan_III_init3[] = {0x54,0x80,0x09/* patch */,0xa0,0x00,0x00}; + +/* hf register */ +unsigned char scan_init4[] = {0x15,0xa0,0xff,0x00/* &0x3f */,0x5f,0x04,0x00}; + +/* dip control */ +unsigned char scan_init5[] = {0x27,0x00,0xff,0x00,0x5f,0x05,0x00}; + +/* dip control */ +unsigned char sync_init1[] = {0x27,0x00,0xff,0x00,0x5f,0x04,0x00}; +unsigned char sync_init2[] = {0xc2,0x05,0x00,0x03,0x00,0x00}; + +/* hf register type II card */ +unsigned char sync_II_init3[] = {0x54,0x80,0x09/* patch */,0xa0,0x00,0x00}; +/* hf register type III card */ +unsigned char sync_III_init3[] = {0x54,0x80,0x09/* patch */,0xa0,0x00,0x00}; +/* hf register */ +unsigned char sync_init4[] = {0x15,0xa0,0xff,0x00/* &0x3f */,0x5f,0x04,0x00}; +/* dip control */ +unsigned char sync_init5[] = {0x27,0x00,0xff,0x00,0x5f,0x05,0x00}; + + +unsigned char fppacket[53] = {0xAA,0xAA,0xAA,0xE9,0x8A}; +unsigned char pppacket[53] = {0x55,0x55,0x55,0x16,0x75}; + + +/* FIXME:auto-generate all this stuff */ +#define PP0 0x4 +#define PP2 0x6 +#define PP4 0x8 +#define PP6 0xA +#define PP8 0xC +#define PP10 0xE +#define PP12 0x11 +#define PP14 0x13 +#define PP16 0x15 +#define PP18 0x17 +#define PP20 0x19 +#define PP22 0x1B +#define JP0 0x3 +#define JP2 0x5 +#define JP4 0x7 +#define JP6 0x9 +#define JP8 0xB +#define JP10 0xD +#define JP12 0x10 +#define JP14 0x12 +#define JP16 0x14 +#define JP18 0x16 +#define JP20 0x18 +#define JP22 0x1A +#define sync_label_D1 0xC8 +#define sync_label_D4 0xCB +#define sync_label_28 0x1F + + +int sync_jumptable[] = { + JP0, 0, + JP2, 0, + JP4, 0, + JP6, 0, + JP8, 0, + JP10, 0, + JP12, 0, + JP14, 0, + JP16, 0, + JP18, 0, + JP20, 0, + JP22, 0 +}; +int sync_patchtable[] = { + PP0, 0, + PP2, 0, + PP4, 0, + PP6, 0, + PP8, 0, + PP10, 0, + PP12, 0, + PP14, 0, + PP16, 0, + PP18, 0, + PP20, 0, + PP22, 0 +}; +/* FIXME:end */ + +int sync_banktable[] = { + SC14421_RAMBANK1, + SC14421_RAMBANK1, + SC14421_RAMBANK1, + SC14421_RAMBANK1, + SC14421_RAMBANK2, + SC14421_RAMBANK2, + SC14421_RAMBANK2, + SC14421_RAMBANK2, + SC14421_RAMBANK3, + SC14421_RAMBANK3, + SC14421_RAMBANK3, + SC14421_RAMBANK3, + SC14421_RAMBANK4, + SC14421_RAMBANK4, + SC14421_RAMBANK4, + SC14421_RAMBANK4, + SC14421_RAMBANK5, + SC14421_RAMBANK5, + SC14421_RAMBANK5, + SC14421_RAMBANK5, + SC14421_RAMBANK6, + SC14421_RAMBANK6, + SC14421_RAMBANK6, + SC14421_RAMBANK6 +}; + + +void sniffer_init(struct coa_info *dev) +{ + int ret; + + SC14421_switch_to_bank( + dev->sc14421_base, + SC14421_DIPSTOPPED | SC14421_CODEBANK + ); + + ret = SC14421_check_RAM(dev->sc14421_base); + if (ret) + printk("Found %u memory r/w errors \n\n", ret); + + switch(dev->sniffer_config->snifftype) + { + case SNIFF_SCANFP: + case SNIFF_SCANPP: + sniffer_init_sniff_scan(dev); + break; + case SNIFF_SYNC: + sniffer_init_sniff_sync(dev); + break; + } +} + +void sniffer_init_sniff_scan(struct coa_info *dev) +{ + uint16_t *sc14421_base = dev->sc14421_base; + +/* printk("loading sniff_scan firmware\n"); */ + + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_CODEBANK + ); + to_dip( + sc14421_base, + sc14421_II_sniff_scan_fw, + ARRAY_SIZE(sc14421_II_sniff_scan_fw)); + + SC14421_clear_interrupt(sc14421_base); + + /* set channel */ + switch(dev->radio_type) + { + case COA_RADIO_TYPE_II: + scan_II_init3[0] = + (scan_II_init3[0] & 0xC1) | + ((10 - dev->sniffer_config->channel) << 1); + break; + default: + printk("ERROR: this radio type is currently not " + "supported. please update the driver\n"); + } + + if (dev->sniffer_config->snifftype == SNIFF_SCANPP) + { + scan_init1[0] &= 0xFE; + scan_init5[0] &= 0xFE; + } + else + { + scan_init1[0] |= 0x01; + scan_init5[0] |= 0x01; + } + + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_RAMBANK0 + ); + to_dip( + sc14421_base + 0x00, + scan_init1, + ARRAY_SIZE(scan_init1)); + to_dip( + sc14421_base + 0x10, + scan_init2, + ARRAY_SIZE(scan_init2) + ); + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_RAMBANK1 + ); + to_dip( + sc14421_base + 0x4A, + scan_II_init3, + ARRAY_SIZE(scan_II_init3) + ); + to_dip( + sc14421_base + 0x58, + scan_init5, + ARRAY_SIZE(scan_init5) + ); + to_dip( + sc14421_base + 0x50, + scan_init4, + ARRAY_SIZE(scan_init4)); + +/* printk("starting dip\n"); */ + SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK0); + +} + + +void sniffer_init_sniff_sync(struct coa_info *dev) +{ + uint16_t *sc14421_base = dev->sc14421_base; + + printk("loading sniff_sync firmware\n"); + + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_CODEBANK + ); + to_dip( + sc14421_base, + sc14421_II_sniff_sync_fw, + ARRAY_SIZE(sc14421_II_sniff_sync_fw)); + + printk("clear interrupt\n"); + SC14421_clear_interrupt(sc14421_base); + + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_RAMBANK0 + ); + to_dip( + sc14421_base + 0x00, + sync_init1, + ARRAY_SIZE(sync_init1) + ); + to_dip( + sc14421_base + 0x10, + sync_init2, + ARRAY_SIZE(sync_init2)); + + /* set channel */ + switch(dev->radio_type) + { + case COA_RADIO_TYPE_II: + sync_II_init3[0] = + (scan_II_init3[0] & 0xC1) | + ( (10 - dev->sniffer_config->channel) << 1); + break; + default: + printk("ERROR: this radio type is currently not " + "supported. please update the driver\n"); + ; + } + + sync_init5[0] |= 0x01; + + + SC14421_switch_to_bank( + sc14421_base, + SC14421_DIPSTOPPED | SC14421_RAMBANK1 + ); + to_dip( + sc14421_base + 0x4A, + sync_II_init3, + ARRAY_SIZE(sync_II_init3) + ); + to_dip( + sc14421_base + 0x58, + sync_init5, + ARRAY_SIZE(sync_init5) + ); + to_dip( + sc14421_base + 0x50, + sync_init4, + ARRAY_SIZE(sync_init4) + ); + + dev->sniffer_config->status = 0; + sniffer_clear_slottable(dev->sniffer_config->slottable); + + + printk("starting dip\n"); + SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK0); + +} + +void sniffer_irq_handler(struct coa_info *dev) +{ + int irq; + + if (dev->sc14421_base) + { + irq = SC14421_clear_interrupt(dev->sc14421_base); + + switch(dev->sniffer_config->snifftype) + { + case SNIFF_SCANFP: + case SNIFF_SCANPP: + sniffer_sniff_scan_irq(dev, irq); + break; + case SNIFF_SYNC: + sniffer_sniff_sync_irq(dev, irq); + break; + } + } + +} + +void sniffer_sniff_scan_irq(struct coa_info *dev, int irq) +{ + volatile uint16_t *sc14421_base = dev->sc14421_base; + + if (dev->open) + { + SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK1); + + if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */ + { + uint8_t rssi = SC14421_READ(0); + from_dip( + fppacket + 5, + sc14421_base + 6, + 6); + + SC14421_WRITE(1, 0); /* Clear Checksum-Flag */ + + if (dect_is_RFPI_Packet(fppacket)) + { + int ret; + uint8_t station[7]; + + station[0] = dev->sniffer_config->channel; + station[1] = rssi; + memcpy(&station[2], &fppacket[6], 5); /* RFPI */ + + ret = kfifo_put(dev->rx_fifo, station, 7); + if (ret <= 0) + { + printk("com_on_air_cs: rx fifo full? " + "kfifo_put() = %d\n", ret); + } + } + } + } +} + +void sniffer_sniff_sync_irq(struct coa_info *dev, int irq) +{ + volatile uint16_t *sc14421_base = dev->sc14421_base; + struct sniffer_cfg *config = dev->sniffer_config; + + int r; + SC14421_switch_to_bank(sc14421_base, SC14421_RAMBANK1); + + + if (!(config->status & SNIFF_STATUS_FOUNDSTATION)) + { + if (irq & 0x01) + { +#if 0 + printk("N:"); + for (r=0; r<16; r++) + printk("%.2x ", SC14421_READ(r)); + + printk("\n"); +#endif + if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */ + { + SC14421_WRITE(1, 0); /* clear checksum flag */ + + from_dip( + fppacket + 5, + sc14421_base + 6, + 6); + + if (dect_compare_RFPI(fppacket, config->RFPI)) + { + printk("found station for sync\n"); + config->status |= + SNIFF_STATUS_FOUNDSTATION; + + SC14421_switch_to_bank( + sc14421_base, + SC14421_CODEBANK + ); + SC14421_write_cmd( + sc14421_base, + sync_label_D4, + BR, + sync_label_D1 + ); + } + } + } + } + else if (!(config->status & SNIFF_STATUS_INSYNC)) + { + if (irq & 0x01) + { + int slot; + int i; + +#if 0 + printk("S:"); + for (i=0; i<16; i++) + printk("%.2x ", SC14421_READ(i)); + printk("\n"); +#endif + if ( (SC14421_READ(1) & 0xc0) == 0xc0) /* Checksum ok */ + { + SC14421_WRITE(1, 0); /* clear checksum flag */ + from_dip( + fppacket + 5, + sc14421_base + 6, + 48); + + slot = dect_get_slot(fppacket); + if (slot != -1) + { + /* printk("station in slot %u\n", slot); */ + config->status |= SNIFF_STATUS_INSYNC; + slot %= 12; + if (slot%2) + printk("slot not possible " + "with this firmware\n"); + + config->slottable[slot].active = 1; + config->slottable[slot].channel = + config->channel; + config->slottable[slot].type = + DECT_SLOTTYPE_CARRIER; + config->slottable[slot].errcnt = 0; + + sniffer_sync_patchloop( + dev, + config->slottable, + SNIFF_SLOTPATCH_FP + ); + sniffer_sync_patchloop( + dev, + config->slottable, + SNIFF_SLOTPATCH_PP + ); + + SC14421_switch_to_bank( + sc14421_base, + SC14421_CODEBANK + ); + printk("set jump to %u\n", + sync_jumptable[slot]); + SC14421_write_cmd( + sc14421_base, + sync_label_D4, + BR, + sync_jumptable[slot] + ); + + printk("we are in sync :)\n"); + + + struct sniffed_packet packet; + + packet.rssi = SC14421_READ(0x00); + packet.channel = config->channel; + packet.slot = slot; + memcpy(packet.data, fppacket, 53); + + int ret; + packet.timestamp = + dev->irq_timestamp; + ret = kfifo_put( + dev->rx_fifo, + (unsigned char*) &packet, + sizeof(struct sniffed_packet)); + if (ret <= 0) + printk("com_on_air_cs: rx fifo " + "full? kfifo_put() " + "= %d\n", ret); + } + } + } + } + else + { + int i, a; + if ( (irq & 0x09) == 0x09) + printk("interrupt too slow , lost packets!\n"); + + if (irq & 0x01) + { + + for (a=0; a<12; a++) + { + if (config->slottable[a].active) + { + int memofs; + + SC14421_switch_to_bank( + sc14421_base, + sync_banktable[a]); + + if ( (a/2) % 2) + memofs = 0x80; + else + memofs = 0x00; + + if ( (SC14421_READ(1+memofs) & 0xc0) == + 0xc0) /* Checksum ok */ + { + struct sniffed_packet packet; +/* fixing indention / coding style is useless beyond here + * need to talk to krater about where to cut in functions + * - mazzoo */ + packet.rssi = + SC14421_READ(memofs); + packet.channel = + config->slottable[a].channel; + packet.slot = a; + memcpy( + packet.data, + fppacket, + 5); + from_dip( + &packet.data[5], + sc14421_base+memofs+6, + 48); + + if (config->slottable[a].type == + DECT_SLOTTYPE_SCAN) + /* we received data on a scan-slot , channel is incemented before , but we want hear the old channel */ + { + packet.channel--; + printk("slot in scanmode\n"); + } + + if (dect_is_multiframe_number(packet.data)) /* if there was a multiframe number , then this packet was in frame 8 (0) */ + { + /* printk("found multiframe number\n"); */ + config->framenumber = 1; + } + + /* if (dev->open) */ + { + int ret; + packet.timestamp = dev->irq_timestamp; + ret = kfifo_put(dev->rx_fifo, (unsigned char*) &packet, sizeof(struct sniffed_packet)); + if (ret <= 0) + { + printk("com_on_air_cs: rx fifo full? kfifo_put() = %d\n", ret); + } + } + + + +#if 0 + printk("F:"); + for (i=0; i<16; i++) + printk("%.2x ", SC14421_READ(i+memofs)); + + printk(" : %.2x : %x\n", irq, a); +#endif + SC14421_WRITE(1+memofs, 0); /* clear checksum flag */ + + + if (dect_update_slottable(config->slottable, a, packet.data)) + { + config->updateppslots = 1; + config->updatefpslots = 1; + /* printk("new slot , must update slots\n"); */ + } + + } + else + { + if (dect_receive_error(config->slottable, a)) + { + config->updateppslots = 1; + config->updatefpslots = 1; + printk("died slot , must update slots\n"); + } + } + } + } + + if ( (!(irq & 0x08)) && (config->updatefpslots) ) + { + /* printk("patching fp slots\n"); */ + sniffer_sync_patchloop(dev, config->slottable, SNIFF_SLOTPATCH_FP); + config->updatefpslots = 0; + } + + } + + if (irq & 0x08) + { + + for (a=12; a<24; a++) + { + if (config->slottable[a].active) + { + int memofs; + + SC14421_switch_to_bank(sc14421_base, sync_banktable[a]); + + if ( (a/2) % 2) + memofs = 0x80; + else + memofs = 0x00; + + if ( (SC14421_READ(1+memofs) & 0xc0) == 0xc0) /* Checksum ok */ + { + struct sniffed_packet packet; + + packet.rssi = SC14421_READ(memofs); + packet.channel = config->slottable[a].channel; + packet.slot = a; + memcpy(packet.data, pppacket, 5); + from_dip(&packet.data[5], sc14421_base+memofs+6, 48); + if (config->slottable[a].type == DECT_SLOTTYPE_SCAN) + { + packet.channel--; + printk("slot in scanmode\n"); + } + + /* if (dev->open) */ + { + int ret; + packet.timestamp = dev->irq_timestamp; + ret = kfifo_put(dev->rx_fifo, (unsigned char*) &packet, sizeof(struct sniffed_packet)); + if (ret <= 0) + { + printk("com_on_air_cs: rx fifo full? kfifo_put() = %d\n", ret); + } + } + + +#if 0 + printk("F:"); + for (i=0; i<16; i++) + printk("%.2x ", SC14421_READ(i+memofs)); + + printk(" : %.2x : %x\n", irq, a); +#endif + + SC14421_WRITE(1+memofs, 0); /* clear checksum flag */ + + + if (dect_update_slottable(config->slottable, a, packet.data)) + { + config->updateppslots = 1; + config->updatefpslots = 1; + /* printk("new slot , must update slots\n"); */ + } + + } + else + { + if (dect_receive_error(config->slottable, a)) + { + config->updateppslots = 1; + config->updatefpslots = 1; + /* printk("died slot , must update slots\n"); */ + } + } + + } + + } + + if ( (!(irq & 0x01)) && (config->updateppslots) ) + { + /* printk("patching pp slots\n"); */ + sniffer_sync_patchloop(dev, config->slottable, SNIFF_SLOTPATCH_PP); + config->updateppslots = 0; + } + + if (dect_update_scanchannels(config->slottable)) + { + config->updateppslots = 1; + config->updatefpslots = 1; + /* printk("new slot , must update slots\n"); */ + } + + if (config->framenumber >= 7) + config->framenumber = 0; + else + config->framenumber++; + } + + } +} + + +void sniffer_sync_patchloop(struct coa_info *dev, struct dect_slot_info *slottable, int type) +{ + int slot, offset = 0; + volatile uint16_t *sc14421_base = dev->sc14421_base; + struct sniffer_cfg *config = dev->sniffer_config; + + + if (type == SNIFF_SLOTPATCH_PP) + offset = 12; + + for (slot = offset; slot < (offset+12); slot++) + { + if (slottable[slot].update) + { + slottable[slot].update = 0; + + if (slottable[slot].active && (slot%2)) + { + static int fixme_count = 23; + if (fixme_count) + { + fixme_count--; + printk("can't use slot %u with this firmware !\n", slot); + } + continue; + } + + + if (slottable[slot].active) + { + int memofs; + + /* set channel */ + switch(dev->radio_type) + { + case COA_RADIO_TYPE_II: + sync_II_init3[0] = (sync_II_init3[0] & 0xC1) | ((10-slottable[slot].channel) << 1); + break; + default: + printk("ERROR: this radio type is currently not supported. please update the driver\n"); + } + + if (slot > 11) + sync_init5[0] &= 0xFE; + else + sync_init5[0] |= 0x01; + + if ( (slot/2) % 2) + memofs = 0x80; + else + memofs = 0x00; + + sync_init5[6] = config->framenumber%8; + + SC14421_switch_to_bank(sc14421_base, sync_banktable[slot]); + + to_dip(sc14421_base + 0x4A + memofs, sync_II_init3, ARRAY_SIZE(sync_II_init3)); + to_dip(sc14421_base + 0x58 + memofs, sync_init5, ARRAY_SIZE(sync_init5)); + to_dip(sc14421_base + 0x50 + memofs, sync_init4, ARRAY_SIZE(sync_init4)); + + + /* printk("patching slot %u at addr %u\n", slot, sync_patchtable[slot]); */ + SC14421_switch_to_bank(sc14421_base, SC14421_CODEBANK); + SC14421_write_cmd(sc14421_base, sync_patchtable[slot], JMP, sync_label_28); + + } + else + { + SC14421_switch_to_bank(sc14421_base, SC14421_CODEBANK); + SC14421_write_cmd(sc14421_base, sync_patchtable[slot], WNT, 2); + /* printk("patching addr %u for wait\n", sync_patchtable[slot]); */ + } + } + else if (slottable[slot].active && (slottable[slot].type == DECT_SLOTTYPE_CARRIER)) + { + SC14421_switch_to_bank(sc14421_base, sync_banktable[slot]); + SC14421_WRITE(0x5e, config->framenumber%8); + } + } +} + + +void sniffer_clear_slottable(struct dect_slot_info *slottable) +{ + int i; + for (i=0; i<24; i++) + { + slottable[i].active = 0; + slottable[i].update = 1; + } +} + + diff --git a/com-on-air_cs-linux/sc14421_sniffer.h b/com-on-air_cs-linux/sc14421_sniffer.h new file mode 100644 index 0000000..f2f2247 --- /dev/null +++ b/com-on-air_cs-linux/sc14421_sniffer.h @@ -0,0 +1,75 @@ +/* + * com_on_air_cs - basic driver for the Dosch and Amand "com on air" cards + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef SC14421_SNIFF_H +#define SC14421_SNIFF_H + +#include "com_on_air_user.h" + +#define SNIFF_SCANFP COA_SUBMODE_SNIFF_SCANFP +#define SNIFF_SCANPP COA_SUBMODE_SNIFF_SCANPP +#define SNIFF_SYNC COA_SUBMODE_SNIFF_SYNC + +#define SNIFF_STATUS_FOUNDSTATION 0x80 +#define SNIFF_STATUS_INSYNC 0x40 + +#define SNIFF_SLOTPATCH_FP 0 +#define SNIFF_SLOTPATCH_PP 1 + +#include "dect.h" +#include "com_on_air.h" + +struct sniffer_cfg +{ + int snifftype; + int channel; + unsigned char RFPI[5]; + unsigned char status; + struct dect_slot_info slottable[24]; + int framenumber; + int updatefpslots; + int updateppslots; +}; + +struct sniffed_rfpi +{ + unsigned char rssi; + unsigned char channel; + unsigned char RFPI[5]; +}; + +#define SLOT_OUT_OF_SYNC 0x20 +#define SLOT_IN_SYNC 0x21 + +struct sniffed_packet +{ + unsigned char rssi; + unsigned char channel; + unsigned char slot; + struct timespec timestamp; + unsigned char data[53]; +}; + + +void sniffer_init(struct coa_info *dev); +void sniffer_init_sniff_all(struct coa_info *dev); +void sniffer_init_sniff_scan(struct coa_info *dev); +void sniffer_init_sniff_sync(struct coa_info *dev); +void sniffer_irq_handler(struct coa_info *dev); +void sniffer_sniff_all_irq(struct coa_info *dev,int irq); +void sniffer_sniff_scan_irq(struct coa_info *dev,int irq); +void sniffer_sniff_sync_irq(struct coa_info *dev,int irq); +void sniffer_sync_patchloop(struct coa_info *dev,struct dect_slot_info *slottable,int type); +void sniffer_clear_slottable(struct dect_slot_info *slottable); +#endif + diff --git a/com-on-air_cs-linux/tools/Makefile b/com-on-air_cs-linux/tools/Makefile new file mode 100644 index 0000000..a95f29d --- /dev/null +++ b/com-on-air_cs-linux/tools/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-Wall -O2 -I.. +PROGS=coa_syncsniff pcap2cchan +PCAP_PROGS=pcapstein dect_cli +all:$(PROGS) $(PCAP_PROGS) + +$(PCAP_PROGS): $(foreach p,$(PCAP_PROGS), $p.c) + $(CC) $(CFLAGS) -lpcap $@.c -o $@ +clean: + rm -f $(PROGS) $(PCAP_PROGS) diff --git a/com-on-air_cs-linux/tools/coa_syncsniff.c b/com-on-air_cs-linux/tools/coa_syncsniff.c new file mode 100644 index 0000000..841102b --- /dev/null +++ b/com-on-air_cs-linux/tools/coa_syncsniff.c @@ -0,0 +1,199 @@ +/* + * coa_syncsniff dumps pcap files on a given channel and RFPI + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "com_on_air_user.h" + + +struct sniffed_packet +{ + unsigned char rssi; + unsigned char channel; + unsigned char slot; + struct timespec timestamp; + unsigned char data[53]; +}; + +struct pcap_global_header +{ + uint32_t magic_number; /* magic number */ + uint16_t version_major; /* major version number */ + uint16_t version_minor; /* minor version number */ + int thiszone; /* GMT to local correction */ + uint32_t sigfigs; /* accuracy of timestamps */ + uint32_t snaplen; /* max length of captured packets, in octets */ + uint32_t network; /* data link type */ +}; + + +struct pcap_record_header +{ + uint32_t ts_sec; /* timestamp seconds */ + uint32_t ts_usec; /* timestamp microseconds */ + uint32_t incl_len; /* number of octets of packet saved in file */ + uint32_t orig_len; /* actual length of packet */ +}; + +void write_global_header(FILE *pcap); +void write_record(FILE *pcap,uint32_t sec,uint32_t usec,uint32_t len,unsigned char *record); + +#define DEV "/dev/coa" + +/* we use some "hidden" ioctls */ +#define COA_IOCTL_TEST0 0xF000 +#define COA_IOCTL_TEST1 0xF001 +#define COA_IOCTL_TEST2 0xF002 +#define COA_IOCTL_TEST3 0xF003 +#define COA_IOCTL_TEST4 0xF004 +#define COA_IOCTL_TEST5 0xF005 +#define COA_IOCTL_TEST6 0xF006 +#define COA_IOCTL_TEST7 0xF007 + + +#define COA_IOCTL_DUMP_DIP_RAM COA_IOCTL_TEST0 +#define COA_IOCTL_FIFO_TEST COA_IOCTL_TEST1 +#define COA_IOCTL_COUNT_IRQ COA_IOCTL_TEST2 + +/* default RFPI */ +uint8_t RFPI[5]={0x00,0x00,0x00,0x00,0x00}; + + +int main(int argc, char *argv[]) +{ + int d; + int ret = 0; + + FILE *pcap; + if(argc<2) + { + printf( "Usage:coa_syncsniff channel pcap-file [RFPI]\n"); + exit(-1); + } + + d=open(DEV, O_RDONLY); + if (d<0) + { + printf("couldn't open(\"%s\"): %s\n", DEV, strerror(errno)); + exit(1); + } + + pcap=fopen(argv[2],"wb"); + if(!pcap) + { + printf("Cant open pcap file for write...\n"); + exit(1); + } + + /* optionally accept RFPI as 3rd argument on commandline */ + if(argc>2) + { + sscanf(argv[3], "%hhx %hhx %hhx %hhx %hhx", &RFPI[0], &RFPI[1], &RFPI[2], &RFPI[3], &RFPI[4]); + printf("RFPI: %02x %02x %02x %02x %02x\n", RFPI[0], RFPI[1], RFPI[2], RFPI[3], RFPI[4]); + } + + + //set sync sniff mode + uint16_t val; + val = COA_MODE_SNIFF|COA_SUBMODE_SNIFF_SYNC; + if(ioctl(d,COA_IOCTL_MODE, &val)){printf("couldn't ioctl()\n");exit(1);} + + //set rfpi to sync with + if(ioctl(d,COA_IOCTL_SETRFPI, RFPI)){printf("couldn't ioctl()\n");exit(1);} + + //set channel + uint32_t chn=atoi(argv[1]); + printf("set channel %u\n",chn); + if(ioctl(d,COA_IOCTL_CHAN,&chn)){printf("couldn't set channel\n");exit(1);} + + + write_global_header(pcap); + + //sniff-loop + while (0xDEC + 't') + { + struct sniffed_packet buf; + while (sizeof(struct sniffed_packet) == (ret = read(d, &buf, (sizeof(struct sniffed_packet))))) + { + unsigned char packet[100]; + packet[12]=0x23; + packet[13]=0x23; + packet[14]=0x00; //decttype (receive) + packet[15]=buf.channel; //channel + packet[16]=0; + packet[17]=buf.slot; //slot + packet[18]=0; + packet[19]=buf.rssi; + memcpy(packet+20,buf.data,53); + + write_record( + pcap, + buf.timestamp.tv_sec, + buf.timestamp.tv_nsec/1000, + 73, + packet); + } + } + + + + + + return ret; +} + + +void write_global_header(FILE *pcap) +{ + struct pcap_global_header header; + + header.magic_number=0xa1b2c3d4; + header.version_major=2; + header.version_minor=4; + header.thiszone=0;//GMT + header.sigfigs=0; + header.snaplen=1024; + header.network=1; + + fwrite(&header,1,sizeof(struct pcap_global_header),pcap); +} + +void write_record(FILE *pcap,uint32_t sec,uint32_t usec,uint32_t len,unsigned char *record) +{ + struct pcap_record_header header; + header.ts_sec=sec; + header.ts_usec=usec; + header.incl_len=len; + header.orig_len=len; + + fwrite(&header,1,sizeof(struct pcap_record_header),pcap); + fwrite(record,1,len,pcap); +} + + diff --git a/com-on-air_cs-linux/tools/dect_c_channel.h b/com-on-air_cs-linux/tools/dect_c_channel.h new file mode 100644 index 0000000..b2f64c0 --- /dev/null +++ b/com-on-air_cs-linux/tools/dect_c_channel.h @@ -0,0 +1,158 @@ +/* + * DECT C channel definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef DECT_CCHAN_H +#define DECT_CCHAN_H + + +struct strtype +{ + char type; + char name[100]; +}; + +struct strtype msgtype[16]= +{ + {0,"0000 LCE (Link Control Entity) messages"}, + {1,""}, + {2,""}, + {3,"0011 CC (Call Control) messages"}, + {4,"0100 CISS (Call Independent Supplementary Services) messages"}, + {5,"0101 MM (Mobility Management) messages"}, + {6,"0110 CLMS (ConnectionLess Message Service) messages"}, + {7,"0111 COMS (Connection Oriented Message Service) messages"} +}; + +struct strtype cctype[256]= +{ + {0x01,"{CC-ALERTING}"}, + {0x02,"{CC-CALL-PROC}"}, + {0x05,"{CC-SETUP}"}, + {0x07,"{CC-CONNECT}"}, + {0x0d,"{CC-SETUP-ACK}"}, + {0x0f,"{CC-CONNECT-ACK}"}, + {0x20,"{CC-SERVICE-CHANGE}"}, + {0x21,"{CC-SERVICE-ACCEPT}"}, + {0x23,"{CC-SERVICE-REJECT}"}, + {0x4d,"{CC-RELEASE}"}, + {0x5a,"{CC-RELEASE-COM}"}, + {0x60,"{IWU-INFO}"}, + {0x6e,"{CC-NOTIFY}"}, + {0x7b,"{CC-INFO}"} +}; + +struct strtype mmtype[256]= +{ + {0x40,"{AUTHENTICATION-REQUEST}"}, + {0x41,"{AUTHENTICATION-REPLY}"}, + {0x42,"{KEY-ALLOCATE}"}, + {0x43,"{AUTHENTICATION-REJECT}"}, + {0x44,"{ACCESS-RIGHTS-REQUEST}"}, + {0x45,"{ACCESS-RIGHTS-ACCEPT}"}, + {0x47,"{ACCESS-RIGHTS-REJECT}"}, + {0x48,"{ACCESS-RIGHTS-TERMINATE-REQUEST}"}, + {0x49,"{ACCESS-RIGHTS-TERMINATE-ACCEPT}"}, + {0x4b,"{ACCESS-RIGHTS-TERMINATE-REJECT}"}, + {0x4c,"{CIPHER-REQUEST}"}, + {0x4e,"{CIPHER-SUGGEST}"}, + {0x4f,"{CIPHER-REJECT}"}, + {0x50,"{MM-INFO-REQUEST}"}, + {0x51,"{MM-INFO-ACCEPT}"}, + {0x52,"{MM-INFO-SUGGEST}"}, + {0x53,"{MM-INFO-REJECT}"}, + {0x54,"{LOCATE-REQUEST}"}, + {0x55,"{LOCATE-ACCEPT}"}, + {0x56,"{DETACH}"}, + {0x57,"{LOCATE-REJECT}"}, + {0x58,"{IDENTITY-REQUEST}"}, + {0x5a,"{IDENTITY-REPLY}"}, + {0x5b,"{MM-IWU}"}, + {0x5c,"{TEMPORARY-IDENTITY-ASSIGN}"}, + {0x5d,"{TEMPORARY-IDENTITY-ASSIGN-ACK}"}, + {0x5f,"{TEMPORARY-IDENTITY-ASSIGN-REJ}"}, + {0x6e,"{MM-NOTIFY}"} +}; + +struct strtype sstype[256]= +{ + {0x24,"{HOLD}"}, + {0x28,"{HOLD-ACK}"}, + {0x30,"{HOLD-REJECT}"}, + {0x31,"{RETRIEVE}"}, + {0x33,"{RETRIEVE-ACK}"}, + {0x37,"{RETRIEVE-REJECT}"}, + {0x5a,"{CISS-RELEASE-COM}"}, + {0x62,"{FACILITY}"}, + {0x64,"{CISS-REGISTER}"}, +}; + + +struct cfrag +{ + int valid; + int slot; + char cttype; + unsigned char data[5]; +}; + +struct cpacket +{ + int valid; + unsigned char addr; + unsigned char ctrl; + unsigned char length; + unsigned char data[80]; + unsigned short checksum; +}; + +struct cdevice +{ + char type; + int found; + char cnt; + int cdata; + struct cpacket packet; +}; + +char lenlookup[64]={ +5,10,10,10,10,10,15,15, +15,15,15,20,20,20,20,20, +25,25,25,25,25,30,30,30, +30,30,35,35,35,35,35,40, +40,40,40,40,45,45,45,45, +45,50,50,50,50,50,55,55, +55,55,55,60,60,60,60,60, +65,65,65,65,65,70,70,70 +}; + +char pklookup[64]={ +1,2,2,2,2,2,3,3, +3,3,3,4,4,4,4,4, +5,5,5,5,5,6,6,6, +6,6,7,7,7,7,7,8, +8,8,8,8,9,9,9,9, +9,10,10,10,10,10,11,11, +11,11,11,12,12,12,12,12, +13,13,13,13,13,14,14,14 +}; + + +struct cfrag getcfrag(unsigned char *dect,int slot); +struct cpacket getcpacket(struct cfrag frag,struct cdevice *device); + +void printcpacket(struct cpacket packet,char *prefix); +char *getstring(struct strtype *str,int id,int max); + + + +#endif diff --git a/com-on-air_cs-linux/tools/dect_cli.c b/com-on-air_cs-linux/tools/dect_cli.c new file mode 100644 index 0000000..1b317f5 --- /dev/null +++ b/com-on-air_cs-linux/tools/dect_cli.c @@ -0,0 +1,671 @@ +/* + * dect_cli async and sync interface to DECT, can dump pcap files + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Matthias Wenzel + * (C) 2008 Andreas Schuler + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "com_on_air_user.h" +#include "dect_cli.h" + +//#define DUMP_IRQ_COUNT_ONCE_PER_SEC + +struct cli_info cli; + + +#define RXBUF 8192 +char buf[RXBUF]; + + +/* pcap errors */ +char errbuf[PCAP_ERRBUF_SIZE]; + +void print_help(void) +{ + LOG("\n"); + LOG(" help - this help\n"); + LOG(" fpscan - async scan for basestations, dump RFPIs\n"); + LOG(" callscan - async scan for active calls, dump RFPIs\n"); + LOG(" autorec - sync on any calls in callscan, autodump in pcap, currently %s\n", cli.autorec ? "ON":"OFF"); + LOG(" ppscan - sync scan for active calls\n"); + LOG(" chan - set current channel [0-9], currently %d\n", cli.channel); +// LOG(" slot - set current slot [0-23], currently %d\n", cli.slot); +// LOG(" jam - jam current channel\n"); + LOG(" dump - dump stations and calls we have seen\n"); + LOG(" hop - toggle channel hopping, currently %s\n", cli.hop ? "ON":"OFF"); + LOG(" verb - toggle verbosity, currently %s\n", cli.verbose ? "ON":"OFF"); + LOG(" stop - stop it - whatever we were doing\n"); + LOG(" quit - well :)\n"); + LOG("\n"); +} + +void set_channel(uint32_t channel) +{ + if (cli.verbose) + LOG("### switching to channel %d\n", channel); + if (ioctl(cli.fd, COA_IOCTL_CHAN, &channel)){ + LOG("!!! couldn't ioctl()\n"); + exit(1); + } + cli.last_hop = time(NULL); +} + +void set_slot(uint32_t slot) +{ + LOG("!!! not yet implemented :(\n"); +} + +void do_ppscan(uint8_t * RFPI) +{ + LOG("### trying to sync on %.2x %.2x %.2x %.2x %.2x\n", + RFPI[0], + RFPI[1], + RFPI[2], + RFPI[3], + RFPI[4] + ); + + /* set sync sniff mode */ + uint16_t val; + val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SYNC; + if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){ + LOG("!!! couldn't ioctl()\n"); + exit(1); + } + + /* set rfpi to sync with */ + if(ioctl(cli.fd, COA_IOCTL_SETRFPI, RFPI)){ + LOG("!!! couldn't ioctl()\n"); + exit(1); + } + + set_channel(cli.channel); + + memcpy(cli.RFPI, RFPI, 5); + cli.mode = MODE_PPSCAN; + + cli.autorec_last_bfield = time(NULL); +} + +void add_station(struct dect_station * station) +{ + int i; + LOG("### found new %s", station->type == TYPE_FP ? "station":"call on"); + for (i=0; i<5; i++) + LOG(" %.2x", station->RFPI[i]); + LOG(" on channel %d RSSI %d\n", station->channel, station->RSSI); + + struct dect_station * p = cli.station_list; + if (p) + { /* append to existing list */ + while (p->next) + p = p->next; + p->next = malloc(sizeof(*p)); + p = p->next; + }else /* create 1st element in list */ + { + cli.station_list = malloc(sizeof(*cli.station_list)); + p = cli.station_list; + } + if (!p) + { + LOG("!!! out of memory\n"); + exit(1); + } + memset(p, 0, sizeof(*p)); + + memcpy(p->RFPI, station->RFPI, 5); + p->channel = station->channel; + p->RSSI = station->RSSI; + p->type = station->type; + p->first_seen = time(NULL); + p->last_seen = p->first_seen; + p->count_seen = 1; + if (cli.autorec) + do_ppscan(station->RFPI); +} + +void try_add_station(struct dect_station * station) +{ + struct dect_station * p = cli.station_list; + int found = 0; + while (p) + { + if (!memcmp(p->RFPI, station->RFPI, 5)) + { + if (p->type == station->type) + { + if ( (p->channel != station->channel) && + (cli.verbose) ) + { + int i; + LOG("### station"); + for (i=0; i<5; i++) + LOG(" %.2x", station->RFPI[i]); + LOG(" switched from channel %d to channel %d\n", + p->channel, + station->channel); + } + found = 1; + p->channel = station->channel; + p->count_seen++; + p->last_seen = time(NULL); + p->RSSI += station->RSSI; /* we avg on dump */ + } + } + p = p->next; + } + if (!found) + add_station(station); +} + + +void do_fpscan(void) +{ + LOG("### starting fpscan\n"); + uint16_t val; + val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SCANFP; + if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){ + LOG("!!! couldn't ioctl()\n"); + exit(1); + } + /* set start channel */ + set_channel(cli.channel); + cli.mode = MODE_FPSCAN; + cli.autorec = 0; +} + +void do_callscan(void) +{ + LOG("### starting callscan\n"); + uint16_t val; + val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SCANPP; + if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){ + LOG("!!! couldn't ioctl()\n"); + exit(1); + } + /* set start channel */ + set_channel(cli.channel); + cli.mode = MODE_CALLSCAN; +} + +void do_ppscan_str(char * str_rfpi) +{ + uint8_t RFPI[5]; + char * end; + int i; + for (i=0; i<5; i++) + { + RFPI[i] = strtoul(str_rfpi, &end, 16); + if ((errno == ERANGE ) + || (errno != 0 && RFPI[i] == 0)) + { + LOG("!!! please enter a valid RFPI (e.g. 00 01 02 03 04)\n"); + return; + } + if (end == str_rfpi) + { + LOG("!!! please enter a valid RFPI (e.g. 00 01 02 03 04)\n"); + return; + } + str_rfpi = end; + } + do_ppscan(RFPI); +} + +void do_chan(char * str_chan) +{ + uint32_t channel; + char * end; + channel = strtoul(str_chan, &end, 0); + if ((errno == ERANGE && (channel == LONG_MAX || channel == LONG_MIN)) + || (errno != 0 && channel == 0)) + { + LOG("!!! please enter a valid channel number [0-9]\n"); + return; + } + if (end == str_chan) + { + LOG("!!! please enter a valid channel number [0-9]\n"); + return; + } + if (channel > 9) + { + LOG("!!! please enter a valid channel number [0-9]\n"); + return; + } + cli.channel = channel; + set_channel(cli.channel); +} + +void do_slot(char * str_chan) +{ + uint32_t slot; + char * end; + slot = strtoul(str_chan, &end, 0); + if ((errno == ERANGE && (slot == LONG_MAX || slot == LONG_MIN)) + || (errno != 0 && slot == 0)) + { + LOG("!!! please enter a valid slot number [0-23]\n"); + return; + } + if (end == str_chan) + { + LOG("!!! please enter a valid slot number [0-23]\n"); + return; + } + if (slot > 23) + { + LOG("!!! please enter a valid slot number [0-23]\n"); + return; + } + cli.slot = slot; + set_slot(cli.slot); +} + +void do_jam(void) +{ + LOG("!!! not yet implemented :(\n"); +} + +void do_dump(void) +{ + int i; + struct dect_station * p = cli.station_list; + if (!p) + { + LOG("### nothing found so far\n"); + return; + } + + LOG("### stations\n"); + do + { + if (p->type == TYPE_FP) + { + LOG(" "); + for (i=0; i<5; i++) + LOG(" %.2x", p->RFPI[i]); + LOG(" ch %1.1d ", p->channel); + LOG(" RSSI %5.2f ", (double)p->RSSI / p->count_seen); + LOG(" count %4.u ", p->count_seen); + LOG(" first %u ", p->first_seen); + LOG(" last %u ", p->last_seen); + LOG("\n"); + } + } while ((p = p->next)); + + p = cli.station_list; + LOG("### calls\n"); + do + { + if (p->type == TYPE_PP) + { + LOG(" "); + for (i=0; i<5; i++) + LOG(" %.2x", p->RFPI[i]); + LOG(" ch %1.1d ", p->channel); + LOG(" RSSI %5.2f ", (double)p->RSSI / p->count_seen); + LOG(" count %4.u ", p->count_seen); + LOG(" first %u ", p->first_seen); + LOG(" last %u ", p->last_seen); + LOG("\n"); + } + } while ((p = p->next)); +} + +void do_hop(void) +{ + cli.hop = cli.hop ? 0:1; + LOG("### channel hopping turned %s\n", cli.hop ? "ON":"OFF"); +} + +void do_verb(void) +{ + cli.verbose = cli.verbose ? 0:1; + LOG("### verbosity turned %s\n", cli.verbose ? "ON":"OFF"); +} + +void do_autorec(void) +{ + cli.autorec = cli.autorec ? 0:1; + LOG("### autorec turned %s\n", cli.autorec ? "ON":"OFF"); +} + +void do_stop(void) +{ + if (!(cli.mode & MODE_STOP)) + { + LOG("### stopping DIP\n"); + uint16_t val; + val = COA_MODE_IDLE; + if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){ + LOG("couldn't ioctl()\n"); + exit(1); + } + cli.mode = MODE_STOP; + cli.autorec = 0; + } +} + +void process_cli_data() +{ + int ret; + ret = read(cli.in, buf, RXBUF); + buf[ret]=0; + if(buf[ret-1] == '\n') + buf[ret-1] = 0; + int done = 0; + if ( !strncasecmp((char *)buf, "help", 4) ) + { print_help(); done = 1; } + if ( !strncasecmp((char *)buf, "fpscan", 6) ) + { do_fpscan(); done = 1; } + if ( !strncasecmp((char *)buf, "callscan", 8) ) + { do_callscan(); done = 1; } + if ( !strncasecmp((char *)buf, "autorec", 7) ) + { do_autorec(); done = 1; } + if ( !strncasecmp((char *)buf, "ppscan", 6) ) + { do_ppscan_str(&buf[6]); done = 1; } + if ( !strncasecmp((char *)buf, "chan", 4) ) + { do_chan(&buf[4]); done = 1; } + if ( !strncasecmp((char *)buf, "slot", 4) ) + { do_slot(&buf[4]); done = 1; } + if ( !strncasecmp((char *)buf, "jam", 3) ) + { do_jam(); done = 1; } + if ( !strncasecmp((char *)buf, "dump", 4) ) + { do_dump(); done = 1; } + if ( !strncasecmp((char *)buf, "hop", 3) ) + { do_hop(); done = 1; } + if ( !strncasecmp((char *)buf, "verb", 4) ) + { do_verb(); done = 1; } + if ( !strncasecmp((char *)buf, "stop", 4) ) + { do_stop(); done = 1; } + if ( !strncasecmp((char *)buf, "quit", 4) ) + { do_stop(); exit(0); } + + if(!done) + LOG("!!! no such command %s\n", buf); + +} + +void init_pcap(struct sniffed_packet * packet) +{ + char fname[100]; + sprintf(fname, "dump_%.2x_%.2x_%.2x_%.2x_%.2x.pcap", + cli.RFPI[0], + cli.RFPI[1], + cli.RFPI[2], + cli.RFPI[3], + cli.RFPI[4]); + LOG("### dumping to %s\n", fname); + cli.pcap = pcap_open_dead(DLT_EN10MB, 73); + if (!cli.pcap) + { + LOG("!!! couldn't pcap_open_dead(\"%s\")\n", fname); + } + cli.pcap_d = pcap_dump_open(cli.pcap, fname); + if (!cli.pcap_d) + { + LOG("!!! couldn't pcap_dump_open(\"%s\")\n", fname); + } +} + +int has_b_field() +{ + if ((cli.packet.data[0x19] & 0x0e) != 0x0e) + return 1; + return 0; +} + +void process_dect_data() +{ + int ret; + switch (cli.mode) + { + case MODE_FPSCAN: + while (7 == (ret = read(cli.fd, buf, 7))){ + memcpy(cli.station.RFPI, &buf[2], 5); + cli.station.channel = buf[0]; + cli.station.RSSI = buf[1]; + cli.station.type = TYPE_FP; + try_add_station(&cli.station); + } + break; + case MODE_CALLSCAN: + while (7 == (ret = read(cli.fd, buf, 7))){ + memcpy(cli.station.RFPI, &buf[2], 5); + cli.station.channel = buf[0]; + cli.station.RSSI = buf[1]; + cli.station.type = TYPE_PP; + try_add_station(&cli.station); + } + break; + case MODE_PPSCAN: + while ( sizeof(cli.packet) == + read(cli.fd, &cli.packet, sizeof(cli.packet))) + { + if (!cli.pcap) + { + LOG("### got sync\n"); + init_pcap(&cli.packet); + /* this is not actually a B-Field, + * but we expect some to come soon + * and the val needs to be non-0 */ + cli.autorec_last_bfield = time(NULL); + } + if (has_b_field()) + cli.autorec_last_bfield = time(NULL); + + struct pcap_pkthdr pcap_hdr; + pcap_hdr.caplen = 73; + pcap_hdr.len = 73; + ret = gettimeofday(&pcap_hdr.ts, NULL); + if (ret) + { + LOG("!!! couldn't gettimeofday(): %s\n", + strerror(errno)); + exit(1); + } + uint8_t pcap_packet[100]; + memset(pcap_packet, 0, 100); + pcap_packet[12] = 0x23; + pcap_packet[13] = 0x23; + pcap_packet[14] = 0x00; /* decttype (receive) */ + pcap_packet[15] = cli.packet.channel; + pcap_packet[16] = 0; + pcap_packet[17] = cli.packet.slot; + pcap_packet[18] = 0; + pcap_packet[19] = cli.packet.rssi; + memcpy(&pcap_packet[20], cli.packet.data, 53); + + pcap_dump(cli.pcap_d, &pcap_hdr, pcap_packet); + } + break; + } +} + +void init_dect() +{ + cli.fd = open(DEV, O_RDWR | O_NONBLOCK); + if (cli.fd < 0) + { + LOG("!!! couldn't open(\"%s\"): %s\n", + DEV, + strerror(errno)); + exit(1); + } + cli.pcap = NULL; +} + +void init_cli() +{ + cli.channel = 0; + cli.slot = 0; + cli.hop = 1; + cli.hop_ch_time = 1; /* in sec */ + + cli.mode = MODE_STOP; + + cli.in = fileno(stdin); + + cli.verbose = 0; + + cli.station_list = NULL; + + cli.autorec = 0; + cli.autorec_timeout = 10; + cli.autorec_last_bfield = 0; +} + +void init(void) +{ + init_dect(); + init_cli(); +} + +int max_int(int a, int b) +{ + if (a>b) + return a; + else + return b; +} + +void mainloop(void) +{ + fd_set rfd; + fd_set wfd; + fd_set efd; + + int nfds = max_int(cli.in, cli.fd); + nfds++; + + struct timeval tv; + + int ret; + +#ifdef DUMP_IRQ_COUNT_ONCE_PER_SEC +#define COA_IOCTL_COUNT_IRQ 0xF002 + uint32_t lasttime = time(NULL); +#endif + + + while (0xDEC + 'T') + { + tv.tv_sec = 1; + tv.tv_usec = 0; + + FD_ZERO(&rfd); + FD_ZERO(&wfd); + FD_ZERO(&efd); + + FD_SET(cli.in, &rfd); + FD_SET(cli.fd, &rfd); + + FD_SET(cli.in, &efd); + FD_SET(cli.fd, &efd); + + ret = select(nfds, &rfd, &wfd, &efd, &tv); + if (ret < 0) + { + LOG("!!! select()\n"); + exit(1); + } + if (FD_ISSET(cli.in, &efd)) + { + LOG("!!! select() on in: %s\n", + strerror(errno)); + exit(1); + } + if (FD_ISSET(cli.fd, &efd)) + { + LOG("!!! select() on fd: %s\n", + strerror(errno)); + exit(1); + } + + if (FD_ISSET(cli.in, &rfd)) + process_cli_data(); + if (FD_ISSET(cli.fd, &rfd)) + process_dect_data(); + +#ifdef DUMP_IRQ_COUNT_ONCE_PER_SEC + if (!(cli.mode & MODE_STOP)) + if (time(NULL) >= lasttime + 1) + { + if (ioctl(cli.fd, COA_IOCTL_COUNT_IRQ, NULL)) + { + printf("couldn't ioctl()\n"); + exit(1); + } + lasttime = time(NULL); + } +#endif + + if( (cli.hop) && + ( (cli.mode & MODE_FPSCAN) || + (cli.mode & MODE_CALLSCAN) || + (cli.mode & MODE_JAM ) )) + { + if ( time(NULL) > cli.last_hop + cli.hop_ch_time ) + { + cli.channel++; + cli.channel %= 10; + set_channel(cli.channel); + } + } + + if (cli.autorec) + { + if ( (time (NULL) - cli.autorec_last_bfield + > cli.autorec_timeout) + && + (cli.mode != MODE_CALLSCAN) + ) + { + do_stop(); + do_callscan(); + if (cli.pcap) + { + pcap_dump_close(cli.pcap_d); + pcap_close(cli.pcap); + cli.pcap_d = NULL; + cli.pcap = NULL; + } + } + } + } + +} + +int main(int argc, char ** argv) +{ + init(); + /* make stdout unbuffered */ + setvbuf(stdout,(char*)NULL,_IONBF,0); + printf("DECT command line interface\n"); + printf("type \"help\" if you're lost\n"); + mainloop(); + return 0; +} diff --git a/com-on-air_cs-linux/tools/dect_cli.h b/com-on-air_cs-linux/tools/dect_cli.h new file mode 100644 index 0000000..92e3080 --- /dev/null +++ b/com-on-air_cs-linux/tools/dect_cli.h @@ -0,0 +1,85 @@ +/* + * dect_cli async and sync interface to DECT, can dump pcap files + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef DECT_CLI_H +#define DECT_CLI_H + +#define DEV "/dev/coa" + +// too verbose #define LOG(fmt, args...) printf("%s(): " fmt, __FUNCTION__, ##args) +#define LOG(fmt, args...) printf(fmt, ##args) + + +#define TYPE_FP 23 +#define TYPE_PP 42 + +struct dect_station +{ + struct dect_station * next; + uint8_t RFPI[5]; + uint32_t RSSI; + uint8_t channel; + uint8_t type; + uint32_t first_seen; + uint32_t last_seen; + uint32_t count_seen; +}; + +struct sniffed_packet +{ + unsigned char rssi; + unsigned char channel; + unsigned char slot; + struct timespec timestamp; + unsigned char data[53]; +}; + + +#define MODE_STOP 0x00000001 +#define MODE_FPSCAN 0x00000002 +#define MODE_PPSCAN 0x00000004 +#define MODE_CALLSCAN 0x00000008 +#define MODE_JAM 0x00000010 + + +struct cli_info +{ + uint8_t RFPI[5]; + uint32_t channel; + uint32_t slot; + int hop; + int hop_ch_time; /* in sec */ + uint32_t last_hop; + + uint32_t mode; + + int in; /* stdin */ + int fd; /* filehandle to the DECT-trx */ + + int verbose; + int autorec; + int autorec_timeout; + int autorec_last_bfield; + + /* fpscan (async) list of stations */ + struct dect_station station; + struct dect_station * station_list; + + /* ppscan (sync) */ + struct sniffed_packet packet; + pcap_t * pcap; + pcap_dumper_t * pcap_d; +}; + + +#endif /* DECT_CLI_H */ diff --git a/com-on-air_cs-linux/tools/dectshark/Makefile b/com-on-air_cs-linux/tools/dectshark/Makefile new file mode 100644 index 0000000..8b9ec39 --- /dev/null +++ b/com-on-air_cs-linux/tools/dectshark/Makefile @@ -0,0 +1,6 @@ +CPPFLAGS=-Wall -O2 -I../.. -lcurses -lpthread +dectshark: dectshark.o gui.o foundinfo.o + g++ $(CPPFLAGS) dectshark.cpp gui.cpp foundinfo.cpp -o dectshark + +clean: + rm *.o dectshark diff --git a/com-on-air_cs-linux/tools/dectshark/dectshark.cpp b/com-on-air_cs-linux/tools/dectshark/dectshark.cpp new file mode 100644 index 0000000..53a9740 --- /dev/null +++ b/com-on-air_cs-linux/tools/dectshark/dectshark.cpp @@ -0,0 +1,122 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "com_on_air_user.h" + + +#include "foundinfo.h" +#include "gui.h" + +#define DEV "/dev/coa" + +void *pcap_threadmain(void *threadid); +void *show_threadmain(void *threadid); + + +found_dects founds; +print_gui gui; + +pthread_t pcap_thread; +pthread_t show_thread; + + + +void set_channel(int dev,int channel); + +int main(int argc, char *argv[]) +{ + int ch; + + pthread_create(&pcap_thread, NULL, pcap_threadmain, (void *)0); +// pthread_create(&show_thread, NULL, show_threadmain, (void *)0); + +// while(1); + + gui.work(); + + return 0; +} + + + + + +void *pcap_threadmain(void *threadid) +{ + int tid; + int chn=0,channeltime=0; + int dev; + + dev = open(DEV, O_RDONLY); + if (dev<0){ + printf("couldn't open(\"%s\"): %s\n", DEV, strerror(errno)); + } + + uint16_t val; + val = COA_MODE_SNIFF|COA_SUBMODE_SNIFF_SCANPP; + if (ioctl(dev, COA_IOCTL_MODE, &val)){ + printf("couldn't set sniff mode\n"); + } + + + while(0xDEC + 't') // ;) + { + dect_found found; + + unsigned char buf[7]; + while (7 == (read(dev, buf, 7))) + { + memcpy(found.RFPI,buf+2,5); + found.channel=buf[0]; + found.type=DECT_FOUND_FP; + founds.AddDect(found); + } + + usleep(100000); + channeltime++; + + if(channeltime == 5) + { + chn++; + chn %= 10; + set_channel(dev,chn); + channeltime = 0; + } + } + + pthread_exit(NULL); +} + +void set_channel(int dev,int channel) +{ + if (ioctl(dev, COA_IOCTL_CHAN, &channel)){ + printf("couldn't set channel\n"); + } + + gui.setchannel(channel); +} + + + +void *show_threadmain(void *threadid) +{ + gui.work(); + pthread_exit(NULL); +} + + + + + diff --git a/com-on-air_cs-linux/tools/dectshark/foundinfo.cpp b/com-on-air_cs-linux/tools/dectshark/foundinfo.cpp new file mode 100644 index 0000000..f0d72d7 --- /dev/null +++ b/com-on-air_cs-linux/tools/dectshark/foundinfo.cpp @@ -0,0 +1,97 @@ +#include "foundinfo.h" + +found_dects::found_dects() +{ + pthread_mutex_init(&mutex,NULL); + + listlen=0; + list=(dect_listentry*)malloc(0); +} + +found_dects::~found_dects() +{ + listlen=0; + free(list); + + pthread_mutex_destroy(&mutex); +} + + +void found_dects::AddDect(dect_found found) +{ + unsigned int i; + + pthread_mutex_lock(&mutex); + + for(i=0;i +#include +#include + +#if !defined(FOUNDINFO_H) +#define FOUNDINFO_H + + +#define DECT_FOUND_FP 0 +#define DECT_FOUND_PP 1 +#define DECT_FOUND_LISTENTRY 2 +#define DECT_FOUND_INVALID 0xFFFF + +struct dect_found +{ + unsigned int type; + unsigned char RFPI[5]; + char channel; +}; + + +struct dect_listentry +{ + unsigned char RFPI[5]; + char channel; + unsigned int fppackets; + unsigned int pppackets; + bool valid; +}; + + + +class found_dects +{ +public: + found_dects(); + ~found_dects(); + + void AddDect(dect_found found); + void ClearList(); + dect_listentry GetListEntry(unsigned int entry); + int GetListLength(); + + +protected: + + int listlen; + dect_listentry *list; + + pthread_mutex_t mutex; + +}; + +#endif + diff --git a/com-on-air_cs-linux/tools/dectshark/gui.cpp b/com-on-air_cs-linux/tools/dectshark/gui.cpp new file mode 100644 index 0000000..73b41f7 --- /dev/null +++ b/com-on-air_cs-linux/tools/dectshark/gui.cpp @@ -0,0 +1,247 @@ +#include "gui.h" + +print_gui::print_gui() +{ + selected=startpos=displaypos=0; +} + +print_gui::~print_gui() +{ + endwin(); +} + + +void print_gui::up() +{ + pthread_mutex_lock(&mutex); + + if(founds.GetListLength()<=(SH-7)) + { + if(displaypos>0) + { + displaypos--; + selected--; + } + } + else + { + if(displaypos>0) + { + displaypos--; + selected--; + } + else if(startpos>0) + { + selected--; + startpos--; + } + } + + pthread_mutex_unlock(&mutex); +} + +void print_gui::down() +{ + pthread_mutex_lock(&mutex); + + if(founds.GetListLength()<=(SH-7)) + { + if(displaypos<(founds.GetListLength()-1)) + { + displaypos++; + selected++; + } + } + else + { + if(displaypos<(SH-8)) + { + displaypos++; + selected++; + } + else if(startpos<=(founds.GetListLength()-1-(SH-7))) + { + selected++; + startpos++; + } + + } + + pthread_mutex_unlock(&mutex); +} + +int print_gui::getselected() +{ + pthread_mutex_lock(&mutex); + return selected; + pthread_mutex_unlock(&mutex); +} + + + + +void print_gui::work() +{ + InitCurses(); + + while(1) + { + + if(kbhit_wait(300000)) + { + int ch=wgetch(mainwin); + + switch(ch) + { + case KEY_LEFT: + break; + case KEY_RIGHT: + break; + case KEY_UP: + up(); + break; + case KEY_DOWN: + down(); + break; + case 'l': + //SetLockMode(); + break; + case 'o': + //SetOverviewMode(); + break; + } + } + + pthread_mutex_lock(&mutex); + + PrintFounds(startpos,SH-7,selected); + PrintStatus(startpos,founds.GetListLength(),channel); + + + pthread_mutex_unlock(&mutex); + } + +} + + + +void print_gui::InitCurses() +{ + initscr(); + + + start_color(); + init_pair(1,COLOR_GREEN,COLOR_BLACK); + init_pair(2,COLOR_YELLOW,COLOR_BLACK); + init_pair(3,COLOR_WHITE,COLOR_BLACK); + init_pair(4,COLOR_RED,COLOR_BLACK); + init_pair(5,COLOR_YELLOW,COLOR_GREEN); + + mainwin = newwin(SH-4,SW-20,0,0); + statuswin = newwin(SH,20,0,SW-20); + msgwin = newwin(4,SW-20,SH-4,0); + +// cbreak(); + noecho(); + keypad(mainwin,TRUE); + + wbkgdset(mainwin,(COLOR_PAIR(1)|A_BOLD)); + wbkgdset(statuswin,(COLOR_PAIR(1)|A_BOLD)); + wbkgdset(msgwin,(COLOR_PAIR(1)|A_BOLD)); + + + box(mainwin,0,0); + wattron(mainwin,COLOR_PAIR(3)); + mvwprintw(mainwin,1,1,"RFPI"); + mvwprintw(mainwin,1,13,"Ch"); + mvwprintw(mainwin,1,31,"FP-Pkt"); + mvwprintw(mainwin,1,51,"PP-Pkt"); + wnoutrefresh(mainwin); + + box(statuswin,0,0); + wattron(statuswin,COLOR_PAIR(2)); + mvwprintw(statuswin,1,1,"Station Packets:"); + mvwprintw(statuswin,4,1,"Phone Packets:"); + mvwprintw(statuswin,SH-3,1,"Channel:"); + wnoutrefresh(statuswin); + + box(msgwin,0,0); + wnoutrefresh(msgwin); + + doupdate(); + +} + +void print_gui::RefreshScreen() +{ + wnoutrefresh(mainwin); + wnoutrefresh(statuswin); + wnoutrefresh(msgwin); + + doupdate(); +} + + +void print_gui::PrintFounds(int start,int num,int selected) +{ + int i,y; + + y=2; + for(i=start;i<(start+num);i++) + { + if(i==selected) + wattron(mainwin,COLOR_PAIR(5)); + else + wattron(mainwin,COLOR_PAIR(2)); + + dect_listentry entry=founds.GetListEntry(i); + + if(entry.valid) + { + mvwprintw(mainwin,y,1,"%.2x%.2x%.2x%.2x%.2x ",entry.RFPI[0],entry.RFPI[1],entry.RFPI[2],entry.RFPI[3],entry.RFPI[4]); + mvwprintw(mainwin,y,13,"%.2i %12u %12u",entry.channel,entry.fppackets,entry.pppackets); + y++; + } + } + + wrefresh(mainwin); +} + + +void print_gui::PrintStatus(unsigned int PP,unsigned int FP,int channel) +{ + wattron(statuswin,COLOR_PAIR(3)); + mvwprintw(statuswin,2,1,"%17u",FP); + mvwprintw(statuswin,5,1,"%17u",PP); + + mvwprintw(statuswin,SH-2,16,"%2u",channel); + wrefresh(statuswin); +} + +void print_gui::setchannel(int chn) +{ + pthread_mutex_lock(&mutex); + channel=chn; + pthread_mutex_unlock(&mutex); +} + + +int print_gui::kbhit_wait(int time) +{ + struct timeval tv; + fd_set read_fd; + + tv.tv_sec=0; + tv.tv_usec=time; + + FD_ZERO(&read_fd); + FD_SET(0,&read_fd); + + if(select(1,&read_fd,NULL,NULL,&tv)==-1) + return 0; + + if(FD_ISSET(0,&read_fd)) + return 1; + + return 0; +} diff --git a/com-on-air_cs-linux/tools/dectshark/gui.h b/com-on-air_cs-linux/tools/dectshark/gui.h new file mode 100644 index 0000000..b75b483 --- /dev/null +++ b/com-on-air_cs-linux/tools/dectshark/gui.h @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +#include "foundinfo.h" + +#if !defined(GUI_H) +#define GUI_H + +#define SW 80 +#define SH 25 + +extern found_dects founds; + +class print_gui +{ +public: + print_gui(); + ~print_gui(); + + void work(); + + void up(); + void down(); + + int getselected(); + + + void setchannel(int channel); +protected: + void InitCurses(); + void RefreshScreen(); + void PrintFounds(int start,int num,int selected); + void PrintStatus(unsigned int PP,unsigned int FP,int channel); + int kbhit_wait(int time); + + pthread_mutex_t mutex; + + int selected,startpos,displaypos; + + WINDOW *mainwin; + WINDOW *statuswin; + WINDOW *msgwin; + + int channel; +}; + +#endif diff --git a/com-on-air_cs-linux/tools/pcap2cchan.c b/com-on-air_cs-linux/tools/pcap2cchan.c new file mode 100644 index 0000000..932b323 --- /dev/null +++ b/com-on-air_cs-linux/tools/pcap2cchan.c @@ -0,0 +1,246 @@ +/* + * pcap2cchan dumps C-channel information from pcap files + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include + +#include "dect_c_channel.h" + + + +int main(int argc, char* argv[]) +{ + struct cfrag frag; + struct cpacket cpacket; + + struct cdevice phone,station; + phone.type=station.type=0; + phone.cdata=station.cdata=0; + phone.found=station.found=0; + phone.cnt=station.cnt=0; + + unsigned char packet[135]; + unsigned int length; + + FILE *pcap=fopen(argv[1],"rb"); + + fseek(pcap,0x18,SEEK_SET); + + while(!feof(pcap)) + { + fseek(pcap,12,SEEK_CUR); + fread(&length,4,1,pcap); + + if(length>135) + { + printf("error , packet size too big\n"); + exit(-1); + } + + fread(packet,length,1,pcap); + frag=getcfrag(packet+23,packet[17]); + + if(frag.valid) + { + if(packet[23]==0x16) + { + cpacket=getcpacket(frag,&phone); + + //printf("Frag : %u -> %u:%.2x %.2x %.2x %.2x %.2x\n",frag.slot,frag.cttype,frag.data[0],frag.data[1],frag.data[2],frag.data[3],frag.data[4]); + + if(cpacket.valid) + { + printcpacket(cpacket,"phone "); + } + } + else if(packet[23]==0xe9) + { + cpacket=getcpacket(frag,&station); + + //printf("Frag : %u -> %u:%.2x %.2x %.2x %.2x %.2x\n",frag.slot,frag.cttype,frag.data[0],frag.data[1],frag.data[2],frag.data[3],frag.data[4]); + + + if(cpacket.valid) + printcpacket(cpacket,"station"); + } + + } + + } + + fclose(pcap); + return 0; +} + + +struct cfrag getcfrag(unsigned char *dect,int slot) +{ + struct cfrag frag; + + if((dect[2]&0xc0)==0) //Ct tail (?) + { + frag.valid=1; + + frag.cttype=(dect[2]&0x20)>>5; + frag.slot=slot; + memcpy(frag.data,dect+3,5); + + } + else + frag.valid=0; + + return frag; +} + + +char *getstring(struct strtype *str,int id,int max) +{ + int i; + for(i=0;ipacket.valid=0; + + if((frag.cttype!=device->type)&&(!device->found)) + { + device->packet.addr=frag.data[0]; + device->packet.ctrl=frag.data[1]; + device->packet.length=frag.data[2]; + + if((device->packet.length>>2)>0) + { + device->packet.data[0]=frag.data[3]; + device->packet.data[1]=frag.data[4]; + device->cdata+=2; + device->cnt=1; + device->found=1; + } + else + { + device->packet.checksum=(((unsigned short)(frag.data[3]))<<8)|(frag.data[4]); + device->packet.valid=1; + device->cdata=0; + device->cnt=0; + device->found=0; + } + + device->type=!device->type; + + } + else if(frag.cttype!=device->type) + { + memcpy(device->packet.data+device->cdata,frag.data,5); + device->cdata+=5; + device->cnt++; + device->type=!device->type; + + if(device->cnt>=pklookup[device->packet.length>>2]) + { + device->packet.checksum=(((unsigned short)(frag.data[3]))<<8)|(frag.data[4]); + device->packet.valid=1; + device->cdata=0; + device->cnt=0; + device->found=0; + } + + } + else + { + //printf("packet loss (?)\n"); + device->type=!device->type; + + if(device->found) + { + memset(device->packet.data+device->cdata,0xff,5); + device->cdata+=5; + device->cnt++; + + if(device->cnt>=pklookup[device->packet.length>>2]) + { + device->cdata=0; + device->packet.valid=1; + device->found=0; + + printcpacket(device->packet,"failed "); + } + } + + + getcpacket(frag,device); + + } + + + return device->packet; +} + + + + + +void printcpacket(struct cpacket packet,char *prefix) +{ + int x; + + printf("\n%s: addr:%.2x ctrl:%.2x len:%.2x crc:%.4x",prefix,packet.addr,packet.ctrl,packet.length,packet.checksum); + + if(packet.length>>2) + { + printf(" -> "); + + char id=packet.data[1]; + switch(packet.data[0]&0x0f) + { + case 0: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,NULL); + break; + case 3: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,getstring(cctype,id,256)); + break; + case 4: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,getstring(sstype,id,256)); + break; + case 5: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,getstring(mmtype,id,256)); + break; + case 6: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,NULL); + break; + case 7: + printf("%s :%s",msgtype[packet.data[0]&0x0f].name,NULL); + break; + + default: + printf("reserved "); + break; + } + + printf(" "); + + for(x=0;x<(packet.length>>2);x++) + printf(" %.2x",packet.data[x]); + } + +// printf("\n\n\n"); +} diff --git a/com-on-air_cs-linux/tools/pcapstein.c b/com-on-air_cs-linux/tools/pcapstein.c new file mode 100644 index 0000000..a4e97f6 --- /dev/null +++ b/com-on-air_cs-linux/tools/pcapstein.c @@ -0,0 +1,177 @@ +/* + * pcapstein dumps all B-Fields found in a pcap file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * authors: + * (C) 2008 Andreas Schuler + * (C) 2008 Matthias Wenzel + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcapstein.h" + +struct file_info fi; + +void usage(void) +{ + fprintf(stderr, "usage: pcapstein \n"); + fprintf(stderr, " creates _pp.ima\n"); + fprintf(stderr, " and _fp.ima\n"); + fprintf(stderr, " for further g.721 audio processing\n"); + fprintf(stderr, " e.g. decode and sox\n"); +} + +void init(char * fname) +{ + fi.p = pcap_open_offline(fname, errbuf); + if (!fi.p) + { + fprintf(stderr, "couln't open(\"%s\"): %s\n", + fname, + strerror(errno)); + fprintf(stderr, "pcap error: %s\n", + errbuf); + exit(1); + } + fprintf(stderr, "%s\n", + pcap_lib_version()); + fprintf(stderr, "pcap file version %d.%d\n", + pcap_major_version(fi.p), + pcap_minor_version(fi.p) + ); + + /* output file handles */ + char * imafname = malloc(strlen(fname)+23); + if (!imafname) + { + fprintf(stderr, "out of memory: %s\n", + strerror(errno)); + exit(1); + } + + /* PP output file */ + sprintf(imafname, "%s_pp.ima", fname); + fi.fpp = open(imafname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (!fi.fpp) + { + fprintf(stderr, "couldn't open(\"%s\"): %s\n", + imafname, + strerror(errno)); + exit(1); + } + + /* FP output file */ + sprintf(imafname, "%s_fp.ima", fname); + fi.ffp = open(imafname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (!fi.ffp) + { + fprintf(stderr, "couldn't open(\"%s\"): %s\n", + imafname, + strerror(errno)); + exit(1); + } + + free (imafname); +} + +void process_b_field(const struct pcap_pkthdr *h, const u_char *pkt) +{ + if ( (pkt[0x17] == 0x16) && (pkt[0x18] == 0x75) ) + write(fi.fpp, &pkt[0x21], 40); + else + write(fi.ffp, &pkt[0x21], 40); +} + +void process_pcap_packet( + u_char *user, const struct pcap_pkthdr *h, + const u_char *pkt) +{ +#if 0 + int i; + printf("packet for %s [%u/%u] @%d.%d\n", + user, + h->len, + h->caplen, + h->ts.tv_sec, + h->ts.tv_usec + ); +#endif + + if (pkt[ETH_TYPE_0_OFF] != ETH_TYPE_0) + return; + if (pkt[ETH_TYPE_1_OFF] != ETH_TYPE_1) + return; +#if 0 + for (i=0; i + * (C) 2008 Matthias Wenzel + * + */ + +#ifndef PCAPSTEIN_H +#define PCAPSTEIN_H + +struct file_info +{ + pcap_t * p; + struct pcap_pkthdr rec; /* walks through all packets */ + + int fpp; /* filehandle to PP .ima file */ + int ffp; /* filehandle to FP .ima file */ +}; + +char errbuf[PCAP_ERRBUF_SIZE]; + +#define ETH_TYPE_0_OFF 0x0c +#define ETH_TYPE_1_OFF 0x0d +#define ETH_TYPE_0 0x23 +#define ETH_TYPE_1 0x23 + +#define PKT_OFF_H 0x19 +#define PKT_OFF_TAIL 0x1a +#define PKT_OFF_R_CRC 0x1f +#define PKT_OFF_B_FIELD 0x21 + +#define DECT_H_BA_MASK 0x0e +#define DECT_H_BA_NO_B_FIELD 0x0e +#define DECT_H_BA_HALF_SLOT 0x08 +#define DECT_H_BA_DOUBLE_SLOT 0x04 + + +#endif /* PCAPSTEIN_H */