diff --git a/CMakeLists.txt b/CMakeLists.txt
index 695de2782e4e94ce13bc2a1e0431abc0c91ace0f..d70fbc3c48b5e3ca54af2595c87b40109d83a6a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -280,7 +280,7 @@ add_executable(test-sx1278-serial
 sbs_target(test-sx1278-serial stm32f429zi_stm32f4discovery)
 
 add_executable(test-cc3135 src/tests/drivers/CC3135/test-cc3135.cpp)
-sbs_target(test-cc3135 stm32f407vg_stm32f4discovery)
+sbs_target(test-cc3135 stm32f429zi_stm32f4discovery)
 
 add_executable(test-cc3135-gs src/tests/drivers/CC3135/test-cc3135.cpp)
 sbs_target(test-cc3135-gs stm32f429zi_skyward_ground_station)
diff --git a/src/shared/radio/CC3135/CC3135.cpp b/src/shared/radio/CC3135/CC3135.cpp
index 3e01fe5759c58b913be28826da2ddb0028aad5b0..5124be5ee064891a1cdb787e8da6e88bab6bd167 100644
--- a/src/shared/radio/CC3135/CC3135.cpp
+++ b/src/shared/radio/CC3135/CC3135.cpp
@@ -38,20 +38,37 @@ CC3135::CC3135(std::unique_ptr<ICC3135Iface> &&iface) : iface(std::move(iface))
     irq_wait_thread = thread;
 }
 
-CC3135Defs::DeviceVersion CC3135::getVersion()
+DeviceVersion CC3135::getVersion()
+{
+    DeviceVersion result = {};
+
+    devigeGet(1, 12, Buffer::from(&result));
+    return result;
+}
+
+void CC3135::devigeGet(uint8_t set_id, uint8_t option, Buffer result)
 {
     DeviceSetGet tx_command  = {};
-    tx_command.device_set_id = 1;   // Device get general
-    tx_command.option        = 12;  // Device get general version
+    tx_command.device_set_id = set_id;
+    tx_command.option        = option;
 
-    DeviceSetGet rx_command  = {};
-    DeviceVersion rx_payload = {};
+    DeviceSetGet rx_command = {};
 
     inoutPacketSync(OPCODE_DEVICE_DEVICEGET, Buffer::from(&tx_command),
                     Buffer::null(), OPCODE_DEVICE_DEVICEGETRESPONSE,
-                    Buffer::from(&rx_command), Buffer::from(&rx_payload));
+                    Buffer::from(&rx_command), result);
+}
+
+void CC3135::setMode(CC3135Defs::Mode mode)
+{
+    WlanSetMode tx_command = {};
+    tx_command.mode        = mode;
 
-    return rx_payload;
+    BasicResponse rx_command = {};
+
+    inoutPacketSync(OPCODE_WLAN_SET_MODE, Buffer::from(&tx_command),
+                    Buffer::null(), OPCODE_WLAN_SET_MODE_RESPONSE,
+                    Buffer::from(&rx_command), Buffer::null());
 }
 
 void CC3135::handleIrq()
@@ -117,9 +134,32 @@ void CC3135::defaultPacketHandler(CC3135Defs::ResponseHeader header)
         opToStr(header.inner.opcode), header.inner.opcode, header.dev_status,
         header.socket_tx_failure, header.socket_non_blocking);
 
+    size_t len = header.inner.len;
+
+    switch (header.inner.opcode)
+    {
+        case OPCODE_DEVICE_INITCOMPLETE:
+        {
+            DeviceInitInfo result = {};
+            safeRead(len, Buffer::from(&result));
+
+            TRACE(
+                "[cc3135] Init completen:\n"
+                "- Status: %8x\n"
+                "- Chip Id: %lx\n"
+                "- More Data: %8x\n",
+                result.status, result.chip_id, result.more_data);
+            break;
+        }
+
+        default:
+            break;
+    }
+
     // Dummy read rest of the data
     // TODO: Add async commands
-    dummyRead(header.inner.len);
+    if (len > 0)
+        dummyRead(len);
 }
 
 void CC3135::run()
@@ -129,6 +169,7 @@ void CC3135::run()
     while (true)
     {
         waitForIrq();
+        // Thread::sleep(500);
 
         {
             // Lock the device interface
@@ -186,6 +227,7 @@ void CC3135::readPacket(OpCode opcode, CC3135::Buffer command,
     while (true)
     {
         waitForIrq();
+        // Thread::sleep(500);
 
         // Locking the interface is not needed
 
@@ -201,13 +243,10 @@ void CC3135::readPacket(OpCode opcode, CC3135::Buffer command,
             // Read the rest of the packet
             size_t len = header.inner.len;
 
-            iface->read(command.ptr, std::min(len, command.len));
-            len -= std::min(len, command.len);
+            safeRead(len, command);
+            safeRead(len, payload);
 
-            iface->read(payload.ptr, std::min(len, payload.len));
-            len -= std::min(len, payload.len);
-
-            // Read tail of remanining data
+            // Read tail of remaining data
             if (len > 0)
                 dummyRead(len);
 
@@ -224,8 +263,11 @@ void CC3135::writePacket(OpCode opcode, CC3135::Buffer command,
 
     writeHeader(&header);
 
-    iface->write(command.ptr, command.len);
-    iface->write(payload.ptr, payload.len);
+    if (command.len > 0)
+        iface->write(command.ptr, command.len);
+
+    if (payload.len > 0)
+        iface->write(payload.ptr, payload.len);
 }
 
 void CC3135::readHeader(ResponseHeader *header)
@@ -288,14 +330,15 @@ void CC3135::readHeader(ResponseHeader *header)
     }
 
     // 4. Scan for double syncs
-    /*uint32_t sync;
+    uint32_t sync;
     memcpy(&sync, &buf[0], 4);
-    while(n2hSyncPatternMatch(sync, tx_seq_num)) {
+    while (n2hSyncPatternMatch(sync, tx_seq_num))
+    {
         memmove(&buf[0], &buf[4], 4);
         iface->read(&buf[4], 4);
 
         memcpy(&sync, &buf[0], 4);
-    }*/
+    }
 
     tx_seq_num++;
 
@@ -335,4 +378,13 @@ void CC3135::dummyRead(size_t n)
     iface->read(dummy, n);
 }
 
+void CC3135::safeRead(size_t &len, Buffer buffer)
+{
+    if (buffer.len > 0)
+    {
+        iface->read(buffer.ptr, std::min(len, buffer.len));
+        len -= std::min(len, buffer.len);
+    }
+}
+
 }  // namespace Boardcore
diff --git a/src/shared/radio/CC3135/CC3135.h b/src/shared/radio/CC3135/CC3135.h
index 1925d1959733613d7c4c5b145e8e174c77e6df2d..31d18cdaa3b486aee8fac758837a7da1bde890db 100644
--- a/src/shared/radio/CC3135/CC3135.h
+++ b/src/shared/radio/CC3135/CC3135.h
@@ -49,6 +49,8 @@ public:
 
     CC3135Defs::DeviceVersion getVersion();
 
+    void setMode(CC3135Defs::Mode mode);
+
 private:
     //! Simple buffer for scatter/gather IO
     struct Buffer
@@ -70,6 +72,8 @@ private:
 
     void defaultPacketHandler(CC3135Defs::ResponseHeader header);
 
+    void devigeGet(uint8_t set_id, uint8_t option, Buffer result);
+
     // Functions dedicated to interrupt servicing
 
     //! Wait for an incoming interrupt (only callable in service thread).
@@ -88,7 +92,7 @@ private:
     //! Read packet in input, with proper synchronization.
     void readPacketSync(CC3135Defs::OpCode opcode, Buffer command,
                         Buffer payload);
-    //! Write a apcket in output, with proper synchronization.
+    //! Write a packet in output, with proper synchronization.
     void writePacketSync(CC3135Defs::OpCode opcode, Buffer command,
                          Buffer payload);
 
@@ -106,6 +110,9 @@ private:
     //! Read dummy n bytes.
     void dummyRead(size_t n);
 
+    //! Safely read a buffer, does bound checking
+    void safeRead(size_t &len, Buffer buffer);
+
     miosix::Thread *irq_wait_thread = nullptr;  //< Thread waiting on IRQ
     size_t irq_count                = 0;        //< Number of interrupts
 
diff --git a/src/shared/radio/CC3135/CC3135Defs.h b/src/shared/radio/CC3135/CC3135Defs.h
index affcb713ae3ebad92bdb2e4d2d3edbe9bdab0a5a..06c2fd3eaa64f39c7f250a21465d1049bb07cfd7 100644
--- a/src/shared/radio/CC3135/CC3135Defs.h
+++ b/src/shared/radio/CC3135/CC3135Defs.h
@@ -37,6 +37,15 @@ namespace Boardcore
 namespace CC3135Defs
 {
 
+enum Mode : uint8_t
+{
+    ROLE_STA      = 0,
+    ROLE_RESERVED = 1,
+    ROLE_AP       = 2,
+    ROLE_P2P      = 3,
+    ROLE_TAG      = 4
+};
+
 //! Synchronous message mask.
 constexpr uint16_t OPCODE_SYNC = 1 << 10;
 
@@ -48,9 +57,11 @@ enum OpCode : uint16_t
     OPCODE_DEVICE_DEVICEGETRESPONSE             = 0x0466,
     OPCODE_DEVICE_DEVICESETRESPONSE             = 0x04B7,
     OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT = 0x089A,  //< ????
+    OPCODE_WLAN_SET_MODE_RESPONSE               = 0x0CB4,
     OPCODE_NETAPP_IPACQUIRED                    = 0x1825,  //< ????
     OPCODE_DEVICE_DEVICEGET                     = 0x8466,
     OPCODE_DEVICE_DEVICESET                     = 0x84B7,
+    OPCODE_WLAN_SET_MODE                        = 0x8CB4,
 };
 
 //! Is this message synchronous?
@@ -92,6 +103,19 @@ struct ResponseHeader
 
 typedef GenericHeader RequestHeader;
 
+struct BasicResponse
+{
+    int16_t status;
+    uint16_t sender;
+};
+
+struct DeviceInitInfo
+{
+    int32_t status;
+    int32_t chip_id;
+    int32_t more_data;
+};
+
 struct DeviceSetGet
 {
     uint16_t status;
@@ -100,6 +124,12 @@ struct DeviceSetGet
     uint16_t config_len;
 };
 
+struct WlanSetMode
+{
+    Mode mode;
+    uint8_t _pad[3];
+};
+
 constexpr SyncPattern H2N_SYNC_PATTERN = {0xBBDDEEFF, 0x4321, 0x34, 0x12};
 constexpr SyncPattern H2N_CNYS_PATTERN = {0xBBDDEEFF, 0x8765, 0x78, 0x56};
 
@@ -137,10 +167,14 @@ inline const char *opToStr(OpCode op)
             return "OPCODE_NETAPP_IPACQUIRED";
         case OpCode::OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT:
             return "OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT";
+        case OpCode::OPCODE_WLAN_SET_MODE_RESPONSE:
+            return "OPCODE_WLAN_SET_MODE_RESPONSE";
         case OpCode::OPCODE_DEVICE_DEVICEGET:
             return "OPCODE_DEVICE_DEVICEGET";
         case OpCode::OPCODE_DEVICE_DEVICESET:
             return "OPCODE_DEVICE_DEVICESET";
+        case OpCode::OPCODE_WLAN_SET_MODE:
+            return "OPCODE_WLAN_SET_MODE";
         default:
             return "<unknown>";
     }
diff --git a/src/tests/drivers/CC3135/test-cc3135.cpp b/src/tests/drivers/CC3135/test-cc3135.cpp
index a1979a396659f2ea773ce5b3579cbd1ae9e8cd55..47e575d3c4bce62e6f42dadd116e4bd3c9a8a6a4 100644
--- a/src/tests/drivers/CC3135/test-cc3135.cpp
+++ b/src/tests/drivers/CC3135/test-cc3135.cpp
@@ -85,7 +85,7 @@ using hib  = Gpio<GPIOA_BASE, 6>;
 
 CC3135 *cc3135 = nullptr;
 
-volatile size_t IRQ_COUNT = 0;
+volatile unsigned int IRQ_COUNT = 0;
 
 #if defined _BOARD_STM32F429ZI_SKYWARD_GS
 void __attribute__((used)) EXTI5_IRQHandlerImpl()
@@ -159,7 +159,7 @@ int main()
             {
                 if (last != IRQ_COUNT)
                 {
-                    printf("[cc3135] IRQ: %zu\n", IRQ_COUNT);
+                    printf("[cc3135] IRQ: %u\n", IRQ_COUNT);
                     last = IRQ_COUNT;
                 }
 
@@ -175,7 +175,7 @@ int main()
     GpioPin cs_pin = cs::getPin();
 
     SPIBusConfig config = {};
-    config.clockDivider = SPI::ClockDivider::DIV_128;
+    config.clockDivider = SPI::ClockDivider::DIV_64;
     config.mode         = SPI::Mode::MODE_0;
     config.bitOrder     = SPI::BitOrder::MSB_FIRST;
 
@@ -193,11 +193,13 @@ int main()
 #ifdef CC3135_HIB
     // Reset CC3135
     hib::low();
-    Thread::sleep(10);
+    Thread::sleep(100);
     hib::high();
 #endif
 
-    Thread::sleep(3000);
+    Thread::sleep(500);
+    // cc3135->setMode(CC3135Defs::ROLE_AP);
+    // Thread::sleep(500);
 
     auto version = cc3135->getVersion();
     printf(