atlas0fd00m / rfcat

RfCat - swiss-army knife of ISM band radio
Other
539 stars 115 forks source link

RFCat application for Flipper Zero #155

Open caquino opened 3 months ago

caquino commented 3 months ago

Hi,

I'm exploring the possibility of creating a Flipper Zero app that allows RFCat to use a Flipper as it would work with a Yardstick one or any other compatible device.

Is this something that interests the maintainers of RFCat in participating?

I assume it would either require the full implementation of the protocol, or to package the firmware available in the repo as a Flipper Zero application.

I've reached out to the developers of one of the firmware that can be used on the Flipper Zero to gauge the possibility of such feature and you can see more information over here: https://github.com/Next-Flip/Momentum-Firmware/issues/26

atlas0fd00m commented 3 months ago

hey @caquino , i have to say, i'm a fan of the idea. i've long wondered if someone would want to do this. i have limited time to "contribute" to this initiative, but i'm happy to support and help guide the design.

let me know if i can help you here. hit me at atlas#AT#r4780y.com if you'd rather go direct to email.

@

caquino commented 3 months ago

Thanks, I appreciate the offer!

I started looking at the source code yesterday and getting my development setup configured.

If it is not a problem with you, I think it would be better to keep the conversation here. This way, it can be useful for others going through a similar journey.

caquino commented 3 months ago

@atlas0fd00m, in your opinion, what would be the correct way to go about it? Should we make the flipper emulate one of the existing dongles (YS1, IMME, ...) or make it a new dongle? It is not impossible (as far as I can tell) to create a USB implementation from scratch that will be compatible with libusb, but it would be much simpler to use an existing profile, like a serial port, for example.

atlas0fd00m commented 3 months ago

that makes sense to keep the conversation here.

i'm not entirely sure which way is better. it depends on how the FlipperZero handles the USB port. i notice that it allows the USB to be used by different tools.... so, i'm not very familiar with the internals of the flipper, nor how to write code for it. how do you access the 1101? how do you interface with it? i see that when i plug it in, it shows up as a serial port (ttyACM). how do you make use of that? can you have a FlipperZero tool completely take ownership of the USB port (as in, providing different USB config, endpoints, etc...)?

if you are able to get that granular control, it may make sense to make the Flipper show up similar to a DonsDongle, ChronosDongle, or YS1. the comms wouldn't change significantly, but we'll make use of the mhz settings in Python functions to handle the fact that the 1101 uses 26mhz versus 24mhz for the other dongles, and that changes the calculations for baud/bw/frequency/etc... that math is already done in the python, just need to make the FlipperZero look like a RfCat for comms.

if you can't get granular control over the USB port, you can still implement RfCat comms, but over straight serial. it won't be a 1:1 with RfCat comms, but we can still do it. i'm excited for you! this sounds like a lot of fun. :)

@

caquino commented 3 months ago

Thanks for such detailed answer, I really appreciate your time.

You can take control over the USB port and provide custom endpoints and such like for example this mass storage code

I can't say that I'm also an expert on Flipper development as this is the first idea I had for an app, but I imagine the flow will be something like the following:

graph LR;
    USB --> Application;
    Application --> CC11011;

This is a similar behavior that the GPIO app has, you can use the flipper as a serial adapter by connecting the RX/TX to gpio pins and exposing a serial adapter endpoint via USB. code

I can see some references for DMA access and rx/tx threads on the USB uart bridge app, so I imagine the same can be created for a custom endpoint implementation, but at this stage it is just a guess.

So, I have some concerns about timing and latency that it may introduce, but I'm reading the documentation to see if there is any way that we can try to overcome processing with DMAs and other similar techniques.

So, I have one more question: Is the timing between the USB and the CC11011 critical?

atlas0fd00m commented 3 months ago

np! i can't guarantee quick responses (or that i don't need to be poked again), but that's not because i don't try. :) and i'm certainly invested and care deeply about RfCat and the community it serves.

timing is always "a concern" but i'm guessing it's less of a concern than you are probably thinking. do things well, do them efficiently. think like a piece of hardware :)

there are certainly inefficiencies, and the world goes on. heck, RfCat client (python) hammers EP5 as fast as possible most the time, because USB is completely host-driven (ie. there's no way for the device to say "hey i got something for you!" - at least FS USB like RfCat uses). it's about tolerance, scale (10 ns versus 10 us versus 10 ms), and good programming. race conditions are worse than slow code in most cases. slow code makes you drop a packet here and there. race conditions can lock up the comms channel and give you a bad day (often needing to reset the firmware/client sync...).

it sounds like you may be able to morph the existing USB firmware descriptors and handlers into the FlipperZero! that's pretty cool. that will make the FZ act just like a DonsDongle (or YS1 if you prefer) in many ways, and without having to write the annoying USB DESCRIPTORS all from scratch, or use the VCOM-style stuff they have. that will have the least impact on the Python side, and leave you to "translate" the existing firmware USB code into something that works on the FlipperZero. That means you can reuse some of the firmware event model for the FZ as well. then, instead of writing directly to RF Registers, you'll need to interface with the CC1101 over SPI. you may even choose to insert an abstraction layer that allows the event model code to remain (nearly?) identical to the existing firmware, but move to an API that is implemented for both the CC1111 chips and the CC1101 (masking the details). if you do that, the interesting part will be to translate from the Direct Memory Access approach the Python code currently uses to directly affect RF Registers. totally doable, and probably kind fun.

alternately, you can just take a different approach altogether, using the VCOM method used by other apps (makes /dev/ttyACM0 show up on Linux when you plug in the FZ), and rework the EP5 handlers to work using the straight "serial port" paradigm. up to you. i'll support you best as i can and share my thoughts whichever you choose. i think the other method might be quicker to success? but possibly not, since my brain can't remove the knowledge i gained about USB controller code implementation i gained through this process. Python code will need a few adjustments (an FZ-compatible version will be created, and the correct one selected at initialization.

talk to me more about your concerns. i can't completely discern what you mean from the sentence "I have some concerns... that it may introduce" (not certain what "it" is referring to) if i'm reading you at all well, you're concerned about doing DMA code as a FZ app, or not being able to? DMA was a boon in the RfCat firmware because the cc1111 isn't exactly an overpowered processor. DMA kept me from having to waste precious MCU time copying data around, and was helpful because the CC1111 RF send/recv register is 1 byte in size, and DMA supported moving the data to/from that 1-byte register exactly as it needed to. i started out doing straight mem-copies. the FZ chip is much more powerful, and the radio isn't MMIO. the key is identifying where things are going to fail if they get overrun, and handling that edge case well. that's a general system-thinking that you'll want to do regardless.

keep in mind the scale of things. MAX Baud Rate for the cc1101 is 500kbaud. that's fast for human eyes, but compared to a FZ processor, not insurmountable. do things efficiently, do them well, fix it if it's not good enough, improve it if you think of ways after something is working.

for me, the initial major milestone was getting PING working. for you, it should probably be the same. get something that shows up and responds to CMD_PING appropriately. from there, achieve the goal of reading/writing RF config entries. from there, receive. then transmit (or vice versa). but start out with a bite-sized, achievable goal. the rest will flow from there :)

@