Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers d7a_fs.cpp Source File

d7a_fs.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 #include "dbg.h"
00004 #include "d7a_com.h"
00005 #include "d7a_common.h"
00006 #include "d7a_fs.h"
00007 #include "d7a.h"
00008 #include "d7a_typedefs.h"
00009 
00010 #if 0
00011     #define FS_DPRINT(...)          DPRINT(__VA_ARGS__)
00012     #define FS_DPRINT_DATA(...)     DPRINT_DATA(__VA_ARGS__)
00013     #define FS_FPRINT(...)          FPRINT(__VA_ARGS__)
00014 #else
00015     #define FS_DPRINT(...);
00016     #define FS_DPRINT_DATA(...);
00017     #define FS_FPRINT(...);
00018 #endif
00019 
00020 #define FS_MAX_FILE_QTY     256
00021 #define FS_MAX_MIRROR_QTY   32
00022 #define FS_MAX_WATCHERS_QTY 32
00023 
00024 #define FS_NULL_MAP             0xFF // XXX: this actually removes usage of file 255
00025 
00026 TYPEDEF_STRUCT_PACKED {
00027     uint8_t  id;
00028     uint8_t  cmd;
00029     uint8_t  fid;
00030     uint32_t offset;
00031     uint32_t length;
00032 } d7a_fs_com_req_t;
00033 
00034 TYPEDEF_STRUCT_PACKED {
00035     uint8_t  id;
00036     uint8_t  cmd;
00037     int8_t   status;
00038     uint32_t length;
00039     uint8_t  data[1];
00040 } d7a_fs_com_resp_t;
00041 
00042 typedef struct {
00043     d7a_fs_com_req_t req;
00044     int8_t   status;
00045     void* data;
00046 } d7a_fs_com_t;
00047 
00048 static WriteFileFunction            g_fs_write_file;
00049 static ReadFileFunction             g_fs_read_file;
00050 
00051 static OS_Thread                         g_fs_thread(osPriorityHigh, 512, NULL);
00052 static OS_Queue<d7a_com_rx_msg_t, 8>   g_fs_pkt_queue;
00053 
00054 void d7a_fs_thread();
00055 
00056 d7a_errors_t d7a_fs_open(WriteFileFunction wf, ReadFileFunction rf)
00057 {
00058     FS_FPRINT("\r\n");
00059     
00060     g_fs_write_file = wf;
00061     g_fs_read_file = rf;
00062     
00063     osStatus err = g_fs_thread.start(d7a_fs_thread);
00064     ASSERT(err == osOK, "Failed to start d7a_fs_thread (err: %d)\r\n", err);
00065 
00066     return D7A_ERR_NONE;
00067 }
00068 
00069 d7a_errors_t d7a_fs_close(void)
00070 {
00071     FS_FPRINT("\r\n");
00072 
00073     g_fs_thread.terminate();
00074     
00075     return D7A_ERR_NONE;
00076 }
00077 
00078 static void d7a_fs_msg(uint8_t* buf, uint8_t len, uint8_t id)
00079 {
00080     FS_FPRINT("\r\n");
00081     d7a_com_tx_msg_t msg;
00082     msg.id = id;
00083     msg.pbuf = buf;
00084     msg.plen = len;
00085     msg.alen = 0;
00086     d7a_com_post_msg(&msg);
00087 }
00088 
00089 void d7a_fs_new_pkt(d7a_com_rx_msg_t* pkt)
00090 {
00091     FS_FPRINT("\r\n");
00092     ASSERT(g_fs_pkt_queue.put(pkt) == osOK, "FS queue full!\r\n");
00093 }
00094 
00095 d7a_com_rx_msg_t* d7a_fs_wait_pkt( uint32_t millisec )
00096 {
00097     FS_FPRINT("(millisec:%d)\r\n", millisec);
00098     osEvent evt = g_fs_pkt_queue.get(millisec);
00099     return (evt.status == osEventMessage)? (d7a_com_rx_msg_t*)evt.value.p : NULL;
00100 }
00101 
00102 
00103 #define OP_SIZE_RD      11
00104 #define OP_SIZE_WR      11
00105 #define OP_SIZE_TOUCH   11
00106 #define OP_SIZE_SYNC    11
00107 #define OP_SIZE_STAT    3
00108 #define OP_SIZE_FLUSH   3
00109 #define OP_SIZE_CREATE  11
00110 #define OP_SIZE_RETSTAT (3+4)
00111 #define OP_SIZE_RETDATA (3+4)
00112 uint8_t k_valid_cmd[] = {FS_OP_RD,  FS_OP_WR,  FS_OP_TOUCH  ,FS_OP_STAT,  FS_OP_FLUSH,  FS_OP_CREATE,  FS_OP_SYNC};
00113 uint8_t k_valid_size[]= {OP_SIZE_RD,OP_SIZE_WR,OP_SIZE_TOUCH,OP_SIZE_STAT,OP_SIZE_FLUSH,OP_SIZE_CREATE,OP_SIZE_SYNC};
00114 
00115 // ------------------------------------------------------------------
00116 // |TOKEN|CMD/RESP|             PAYLOAD                         |
00117 // --------------------------------------------------------------
00118 // | 1B  |   1B   |            PKT.blen - 1 bytes               |
00119 // --------------------------------------------------------------
00120 // |     |        |  1B  |   4B   |   4B   | PKT.blen - 11 bytes|
00121 // --------------------------------------------------------------
00122 //  |     | write  | FID  | offset | length | datas...           |
00123 //  |     | read   | FID  | offset | length |
00124 //  |     | touch  | FID  | offset | length |
00125 //  |     | exist  | FID  |
00126 //  |     | flush  | FID  |
00127 //  |     | retstat|status| length | <kal_fs_properties_t>
00128 //  |     | retdat |status| length | datas...                    |
00129 void d7a_fs_thread()
00130 {
00131     FS_FPRINT("(id:0x%08x)\r\n", osThreadGetId());
00132     d7a_com_rx_msg_t* pkt;
00133     int8_t status = FS_STAT_OK;
00134     
00135     while (true)
00136     {
00137         status = FS_STAT_OK;
00138         // TODO: For now only one outgoing-request can be pending
00139         //       An incoming-request response can be served simultaneously
00140         // TODO: handle segmentation. For now MTU = 255-10 = 245
00141         pkt = d7a_fs_wait_pkt();
00142         ASSERT(pkt != NULL, "FS NULL pkt\r\n");
00143         // ---------------------------------------------------------------------------
00144         // Peer request
00145         // ---------------------------------------------------------------------------
00146         switch (pkt->id)
00147         {
00148             case KAL_COM_FLOW_FS_CMD:
00149                 d7a_fs_com_req_t* req = (d7a_fs_com_req_t*)pkt->buffer;
00150                 FS_DPRINT("Rfs[%d](%d) cmd:%d\n", req->fid, req->id, req->cmd);
00151                 //dbg_print_data("%02X ", (uint8_t*)req, sizeof(d7a_fs_com_req_t));
00152                 //FS_DPRINT("\r\n");
00153                 d7a_fs_com_resp_t buf = (d7a_fs_com_resp_t) {.id = req->id, .cmd = FS_OP_RETSTAT};
00154     
00155                 // Error management makes sense here as we face peer-requests,
00156                 // and we don't want to assert because of the peer.
00157                 //status = d7a_fs_check_req(req, pkt->blen);
00158                 //buf.status = status;
00159                 buf.status = FS_STAT_OK;
00160     
00161                 // From here we assume that the request is valid
00162                 // TODO: for now we consider that COM-FS request are targetting
00163                 // FIDs that are "local" to the Host, but we can extend this
00164                 // to "distant" files as well.(i.e. access SPI-Flash of an Host)
00165                 if (status != FS_STAT_OK)
00166                 {
00167                     buf.length = 0;
00168                     // Here we respond to request errors and OP_STAT
00169                     d7a_fs_msg((uint8_t*)&buf,OP_SIZE_RETSTAT, KAL_COM_FLOW_FS_RESP);
00170                 }
00171                 else if (req->cmd == FS_OP_RD)
00172                 {
00173                     d7a_fs_com_resp_t* b = (d7a_fs_com_resp_t*)MALLOC(OP_SIZE_RETDATA + req->length);
00174                     ASSERT(g_fs_read_file != NULL, "FS Read callback not implemented!\r\n");
00175                     uint32_t len = g_fs_read_file(req->fid, req->offset, req->length, &b->data[0]);
00176                     
00177                     b->id     = req->id;
00178                     b->cmd    = FS_OP_RETDATA;
00179                     if (len == req->length)
00180                     {
00181                         b->length = len;
00182                         b->status = FS_STAT_OK;
00183                     }
00184                     else
00185                     {
00186                         b->length = 0;
00187                         b->status = FS_STAT_ERR_FID_NOEXIST;
00188                         WARNING(false, "FS_STAT_ERR_FID_NOEXIST\r\n");
00189                     }
00190                     
00191                     d7a_fs_msg((uint8_t*)b, OP_SIZE_RETDATA + b->length, KAL_COM_FLOW_FS_RESP);
00192                     FREE(b);
00193                 }
00194                 else if (req->cmd == FS_OP_WR)
00195                 {
00196                     ASSERT(g_fs_write_file != NULL, "FS Write callback not implemented!\r\n");
00197                     buf.length = g_fs_write_file(req->fid, req->offset, req->length, &pkt->buffer[OP_SIZE_WR]);
00198                     d7a_fs_msg((uint8_t*)&buf, OP_SIZE_RETSTAT, KAL_COM_FLOW_FS_RESP);
00199                 }
00200                 else if (req->cmd == FS_OP_TOUCH)
00201                 {
00202                     FS_DPRINT("PS Touch f:%d o:%d s:%d\r\n", req->fid, req->offset, req->length);
00203                     //buf.length = g_fs_callback->touch_file(req->fid, req->offset, req->length);
00204                     d7a_fs_msg((uint8_t*)&buf, OP_SIZE_RETSTAT, KAL_COM_FLOW_FS_RESP);
00205                 }
00206                 else
00207                 {
00208                     ASSERT(false, "FS: Unsupported cmd %d\r\n", req->cmd);
00209                 }
00210                 break;
00211             // ---------------------------------------------------------------------------
00212             // Response to our commands
00213             // ---------------------------------------------------------------------------
00214             case KAL_COM_FLOW_FS_RESP:
00215                 ASSERT(false, "FS: Commands are not used\r\n");
00216                 break;
00217             default:
00218                 EPRINT("FS Unknown Flow ID 0x%02X\r\n", pkt->id);
00219                 break;
00220         }
00221         FREE(pkt);
00222     }
00223 }