/** ALP Processor Callback for Starting a Ping <BR> * ========================================================================<BR> * "ALP" is the NDEF-based set of low-level API protocols that OpenTag uses. * ALP messages can come-in over any communication method: wire, wireless, * telepathy... anything that can transfer a packet payload. * * Some ALPs are standardized. Those get handled by OTlib automatically. ALPs * that are not recognized are sent to this function to be handled. In this * demo, we are using a very simple ALP, shown below: * * ALP Payload Length: 0 * ALP Protocol ID: 255 (FF) * ALP Protocol Commands: 0-127 (00-7F) corresponding to channel to sniff * * The "user_id" parameter corresponds to the Device ID that sent this ALP. * * A quickstart guide to the ALP API is available on the Indigresso Wiki. * http://www.indigresso.com/wiki/doku.php?id=opentag:api:quickstart */ void otapi_alpext_proc(alp_tmpl* alp, id_tmpl* user_id) { /// The function app_invoke() will cause the kernel to call ext_systask() as /// soon as resources are available. vlFILE* fp; ot_uni16 scratch; ot_u8 channel; ot_u8 retval; // Start the task only if: Caller is ROOT, ALP Call is Protocol-255, Task is idle if ( auth_isroot(user_id) \ && (alp->inrec.id == 0xFF) \ && (APP_TASK.event == 0) ) { /// Make sure channel is spec-legal. If so, set the channel of the /// first (and only) in the channel list to the specified one, and also /// set the channel of the hold scan accordingly. By default, the scan /// is updated every second. The next scan will have these settings. retval = 0; channel = alp->inrec.cmd & 0x7F; if (((channel & 0xF0) <= 0x20) && ((channel & 0x0F) <= 0x0E)) { fp = ISF_open_su(ISF_ID(channel_configuration)); scratch.ushort = vl_read(fp, 0); scratch.ubyte[0] = channel; vl_write(fp, 0, scratch.ushort); vl_close(fp); fp = ISF_open_su(ISF_ID(hold_scan_sequence)); scratch.ushort = vl_read(fp, 0); scratch.ubyte[0] = channel; vl_write(fp, 0, scratch.ushort); vl_close(fp); retval = 1; //success } alp_load_retval(alp, retval); } }
OT_WEAK void dll_change_settings(ot_u16 new_mask, ot_u16 new_settings) { vlFILE* fp_active; vlFILE* fp_supported; // Get Active Settings, Get Supported Settings, // Mask-out unsupported settings, apply to new active settings ///@todo assert fp fp_active = ISF_open_su( 0x00 ); fp_supported = ISF_open_su( 0x01 ); new_mask &= vl_read(fp_supported, 8); dll.netconf.active = vl_read(fp_active, 4); new_settings &= new_mask; dll.netconf.active &= ~new_mask; dll.netconf.active |= new_settings; // Write the new settings to the ISF 0 vl_write(fp_active, 4, dll.netconf.active); vl_close(fp_active); vl_close(fp_supported); // Flush the System of all Sessions and Events, and restart it sub_dll_flush(); }
ot_int sub_filedata( alp_tmpl* alp, id_tmpl* user_id, ot_u8 respond, ot_u8 cmd_in, ot_int data_in ) { vlFILE* fp; ot_u16 offset; ot_u16 span; ot_int data_out = 0; ot_bool inc_header = (ot_bool)((cmd_in & 0x0F) == 0x0C); vlBLOCK file_block = (vlBLOCK)((cmd_in >> 4) & 0x07); ot_u8 file_mod = ((cmd_in & 0x02) ? VL_ACCESS_W : VL_ACCESS_R); ot_queue* inq = alp->inq; ot_queue* outq = alp->outq; sub_filedata_TOP: while (data_in > 0) { vaddr header; ot_u8 err_code; ot_u8 file_id; ot_u16 limit; //alp->BOOKMARK_IN = inq->getcursor; //alp->BOOKMARK_OUT = NULL; file_id = q_readbyte(inq); offset = q_readshort(inq); span = q_readshort(inq); limit = offset + span; err_code = vl_getheader_vaddr(&header, file_block, file_id, file_mod, user_id); file_mod = ((file_mod & VL_ACCESS_W) != 0); //fp = NULL; // A. File error catcher Stage // (In this case, gotos make it more readable) /// Make sure file header was retrieved properly, or goto error if (err_code != 0) { goto sub_filedata_senderror; } /// Make sure file opens properly, or goto error fp = vl_open_file(header); if (fp == NULL) { err_code = 0xFF; goto sub_filedata_senderror; } /// Make sure offset is within file bounds, or goto error if (offset >= fp->alloc) { err_code = 0x07; goto sub_filedata_senderror; } if (limit > fp->alloc) { limit = fp->alloc; err_code = 0x08; } // B. File Writing or Reading Stage // Write to file // 1. Process error on bad ALP parameters, but still do partial write // 2. offset, span are adjusted to convey leftover data // 3. miscellaneous write error occurs when vl_write fails if (file_mod) { for (; offset<limit; offset+=2, span-=2, data_in-=2) { if (inq->getcursor >= inq->back) { goto sub_filedata_overrun; } err_code |= vl_write(fp, offset, q_readshort_be(inq)); } } // Read from File // 1. No error for bad read parameter, just fix the limit // 2. If inc_header param is set, include the file header in output // 3. Read out file data else { ot_u8 overhead; //limit = (limit > fp->length) ? fp->length : limit; overhead = 6; overhead += (inc_header != 0) << 2; if ((outq->putcursor+overhead) >= outq->back) { goto sub_filedata_overrun; } q_writeshort_be(outq, vworm_read(header + 4)); // id & mod if (inc_header) { q_writeshort(outq, vworm_read(header + 0)); // length q_writeshort(outq, vworm_read(header + 2)); // alloc data_out += 4; } q_writeshort(outq, offset); q_writeshort(outq, span); data_out += 6; for (; offset<limit; offset+=2, span-=2, data_out+=2) { if ((outq->putcursor+2) >= outq->back) { goto sub_filedata_overrun; } q_writeshort_be(outq, vl_read(fp, offset)); } } // C. Error Sending Stage sub_filedata_senderror: if ((respond != 0) && (err_code | file_mod)) { if ((outq->putcursor+2) >= outq->back) { goto sub_filedata_overrun; } q_writebyte(outq, file_id); q_writebyte(outq, err_code); q_markbyte(inq, span); // go past any leftover input data data_out += 2; } data_in -= 5; // 5 bytes input header vl_close(fp); } // Total Completion: // Set bookmark to NULL, because the record was completely processed //alp->BOOKMARK_IN = NULL; return data_out; // Partial or Non Completion: // Reconfigure last ALP operation, because it was not completely processed ///@todo Bookmarking is obsolete, because the way Chunking is done has /// been revised. Chunked records must be contiguous. ALP-Main will not /// call this app, and thus not call this function, until the message-end /// bit is detected, therefore meaning that all data is received and /// contiguous. This overrun block, thus, should only check the flags for /// chunking, bypass them, and loop back to the top of this function. sub_filedata_overrun: vl_close(fp); ///@todo alp_next_chunk(alp); // { // ot_u8* scratch; // inq->getcursor = (ot_u8*)alp->BOOKMARK_IN; // scratch = inq->getcursor + 1; // *scratch++ = ((ot_u8*)&offset)[UPPER]; // *scratch++ = ((ot_u8*)&offset)[LOWER]; // *scratch++ = ((ot_u8*)&span)[UPPER]; // *scratch = ((ot_u8*)&span)[LOWER]; // } return data_out; }