Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[nfcd] D-Bus API for locking tag for exclusive access. JB#46766
D-Bus client performing the I/O needs to be able to ensure
that nothing (no other D-Bus client, not even an internal
presence check) interferes with what it's doing.
  • Loading branch information
monich committed Jul 30, 2019
1 parent f7c2524 commit e47baf1
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 97 deletions.
35 changes: 33 additions & 2 deletions core/include/nfc_tag_t2.h
Expand Up @@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Expand Down Expand Up @@ -100,6 +100,17 @@ nfc_tag_t2_write(
GDestroyNotify destroy,
void* user_data);

guint
nfc_tag_t2_write_seq(
NfcTagType2* tag,
guint sector,
guint block,
GBytes* bytes,
NfcTargetSequence* seq,
NfcTagType2WriteFunc complete,
GDestroyNotify destroy,
void* user_data); /* Since 1.0.17 */

/*
* The methods belows read only the data part of the chip's memory,
* excluding sector headers, trailers or other reserved areas. Blocks
Expand Down Expand Up @@ -142,6 +153,16 @@ nfc_tag_t2_read_data(
GDestroyNotify destroy,
void* user_data);

guint
nfc_tag_t2_read_data_seq(
NfcTagType2* tag,
guint offset,
guint maxbytes,
NfcTargetSequence* seq,
NfcTagType2ReadDataFunc resp,
GDestroyNotify destroy,
void* user_data); /* Since 1.0.17 */

NFC_TAG_T2_IO_STATUS
nfc_tag_t2_read_data_sync(
NfcTagType2* tag,
Expand All @@ -158,6 +179,16 @@ nfc_tag_t2_write_data(
GDestroyNotify destroy,
void* user_data);

guint
nfc_tag_t2_write_data_seq(
NfcTagType2* tag,
guint offset,
GBytes* bytes,
NfcTargetSequence* seq,
NfcTagType2WriteDataFunc complete,
GDestroyNotify destroy,
void* user_data); /* Since 1.0.17 */

#endif /* NFC_TAG_T2_H */

/*
Expand Down
54 changes: 49 additions & 5 deletions core/include/nfc_target.h
Expand Up @@ -50,11 +50,13 @@ struct nfc_target {
/* This one-way flag is set to FALSE when target disappears. */
gboolean present;

/* Several transmissions may have to be performed one after another,
* RECORD SELECT for type 2 tags is an example of that. This flag is
* TRUE when transmission sequence is active. Implementation must not
* insert any internal transmission in the middle of a transmission
* sequence. */
/*
* Several transmissions may have to be performed one after
* another, RECORD SELECT for type 2 tags is an example of that.
* Implementation must not insert any internal transmission in
* the middle of a transmission sequence, not even a presence
* check.
*/
NfcTargetSequence* sequence;
};

Expand All @@ -63,6 +65,48 @@ GType nfc_target_get_type(void);
#define NFC_TARGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
NFC_TYPE_TARGET, NfcTarget))

typedef
void
(*NfcTargetFunc)(
NfcTarget* target,
void* user_data);

gulong
nfc_target_add_sequence_handler(
NfcTarget* target,
NfcTargetFunc func,
void* user_data); /* Since 1.0.17 */

void
nfc_target_remove_handler(
NfcTarget* target,
gulong id); /* Since 1.0.17 */

void
nfc_target_remove_handlers(
NfcTarget* target,
gulong* ids,
guint count); /* Since 1.0.17 */

#define nfc_target_remove_all_handlers(target,ids) \
nfc_target_remove_handlers(target, ids, G_N_ELEMENTS(ids))

/*
* Sometimes it's necessary to guarantee that several transmissions
* are performed one after another (and nothing happens in between).
* That's done by allocating and holding a reference to NfcTargetSequence
* object. As long as NfcTargetSequence is alive, NfcTarget will only
* perform transmissions associated with this sequence.
*/

NfcTargetSequence*
nfc_target_sequence_new(
NfcTarget* target); /* Since 1.0.17 */

void
nfc_target_sequence_free(
NfcTargetSequence* seq); /* Since 1.0.17 */

G_END_DECLS

#endif /* NFC_TARGET_H */
Expand Down
72 changes: 59 additions & 13 deletions core/src/nfc_tag_t2.c
Expand Up @@ -14,8 +14,8 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Expand Down Expand Up @@ -381,7 +381,7 @@ nfc_tag_t2_read_data_free(
{
NfcTagType2ReadData* read = user_data;

nfc_target_sequence_free(read->seq);
nfc_target_sequence_unref(read->seq);
nfc_target_cancel_transmit(read->t2->tag.target, read->cmd_id);
if (read->destroy) {
read->destroy(read->user_data);
Expand Down Expand Up @@ -493,7 +493,7 @@ nfc_tag_t2_write_data_free(
NfcTarget* target = write->t2->tag.target;

nfc_target_remove_handler(target, write->start_id);
nfc_target_sequence_free(write->seq);
nfc_target_sequence_unref(write->seq);
nfc_target_cancel_transmit(target, write->cmd_id);
if (write->destroy) {
write->destroy(write->user_data);
Expand All @@ -509,6 +509,7 @@ nfc_tag_t2_write_data_new(
guint sector_number,
guint offset,
GBytes* bytes,
NfcTargetSequence* seq,
GCallback complete,
GDestroyNotify destroy,
void* user_data)
Expand All @@ -520,7 +521,8 @@ nfc_tag_t2_write_data_new(
write->bytes = g_bytes_ref(bytes);
write->offset = offset;
write->sector_number = sector_number;
write->seq = nfc_target_sequence_new(self->tag.target);
write->seq = seq ? nfc_target_sequence_ref(seq) :
nfc_target_sequence_new(self->tag.target);
write->seq_id = nfc_tag_t2_generate_id(self);
write->complete.cb = complete;
write->destroy = destroy;
Expand Down Expand Up @@ -820,7 +822,7 @@ nfc_tag_t2_initialized(
NfcTag* tag = &self->tag;

if (priv->init_seq) {
nfc_target_sequence_free(priv->init_seq);
nfc_target_sequence_unref(priv->init_seq);
priv->init_seq = NULL;
}
nfc_tag_set_initialized(tag);
Expand Down Expand Up @@ -1063,6 +1065,20 @@ nfc_tag_t2_read_data(
NfcTagType2ReadDataFunc complete,
GDestroyNotify destroy,
void* user_data)
{
return nfc_tag_t2_read_data_seq(self, offset, maxbytes, NULL, complete,
destroy, user_data);
}

guint
nfc_tag_t2_read_data_seq(
NfcTagType2* self,
guint offset,
guint maxbytes,
NfcTargetSequence* seq,
NfcTagType2ReadDataFunc complete,
GDestroyNotify destroy,
void* user_data) /* Since 1.0.17 */
{
#pragma message("TODO: Support more than one sector and cross-sector reads")
if (G_LIKELY(self) && (self->tag.flags & NFC_TAG_FLAG_INITIALIZED)) {
Expand Down Expand Up @@ -1126,7 +1142,8 @@ nfc_tag_t2_read_data(
read->complete_id = g_idle_add(nfc_tag_t2_read_complete, read);
} else {
/* We actually need to read something */
read->seq = nfc_target_sequence_new(self->tag.target);
read->seq = seq ? nfc_target_sequence_ref(seq) :
nfc_target_sequence_new(self->tag.target);
read->cmd_id = nfc_tag_t2_cmd_read(self, header_blocks +
start_block, read->seq, nfc_tag_t2_read_resp, NULL, read);
}
Expand Down Expand Up @@ -1208,6 +1225,21 @@ nfc_tag_t2_write(
NfcTagType2WriteFunc complete,
GDestroyNotify destroy,
void* user_data)
{
return nfc_tag_t2_write_seq(self, sector_number, block, bytes, NULL,
complete, destroy, user_data);
}

guint
nfc_tag_t2_write_seq(
NfcTagType2* self,
guint sector_number,
guint block,
GBytes* bytes,
NfcTargetSequence* seq,
NfcTagType2WriteFunc complete,
GDestroyNotify destroy,
void* user_data) /* Since 1.0.17 */
{
#pragma message("TODO: Support more than one sector and cross-sector writes")
if (G_LIKELY(self) && bytes && sector_number == 0 &&
Expand All @@ -1223,8 +1255,8 @@ nfc_tag_t2_write(
size -= size % block_size;
if (sector && size > 0 && (offset + size) <= sector->size) {
NfcTagType2WriteData* write = nfc_tag_t2_write_data_new(self,
sector_number, offset, bytes, G_CALLBACK(complete), destroy,
user_data);
sector_number, offset, bytes, seq, G_CALLBACK(complete),
destroy, user_data);

GDEBUG("Writing %u blocks starting at %u", (guint)
(size / block_size), block);
Expand All @@ -1237,7 +1269,7 @@ nfc_tag_t2_write(
return 0;
}

/* This one only touches the data area, allows unaligned access */
/* These only touch the data area and allow unaligned access */
guint
nfc_tag_t2_write_data(
NfcTagType2* self,
Expand All @@ -1246,6 +1278,20 @@ nfc_tag_t2_write_data(
NfcTagType2WriteDataFunc complete,
GDestroyNotify destroy,
void* user_data)
{
return nfc_tag_t2_write_data_seq(self, offset, bytes, NULL, complete,
destroy, user_data);
}

guint
nfc_tag_t2_write_data_seq(
NfcTagType2* self,
guint offset,
GBytes* bytes,
NfcTargetSequence* seq,
NfcTagType2WriteDataFunc complete,
GDestroyNotify destroy,
void* user_data) /* Since 1.0.17 */
{
if (G_LIKELY(self) && bytes &&
(self->tag.flags & NFC_TAG_FLAG_INITIALIZED)) {
Expand All @@ -1262,8 +1308,8 @@ nfc_tag_t2_write_data(
if (sector && size > 0 && (offset + size) <= sector->size) {
const guint block_offset = offset % block_size;
NfcTagType2WriteData* write = nfc_tag_t2_write_data_new(self,
sector - priv->sectors, offset, bytes, G_CALLBACK(complete),
destroy, user_data);
sector - priv->sectors, offset, bytes, seq,
G_CALLBACK(complete), destroy, user_data);

GDEBUG("Writing %u data byte(s) starting at offset %u",
(guint)size, offset);
Expand Down Expand Up @@ -1333,7 +1379,7 @@ nfc_tag_t2_finalize(
g_free(priv->sectors);
}
nfc_target_cancel_transmit(self->tag.target, priv->init_id);
nfc_target_sequence_free(priv->init_seq);
nfc_target_sequence_unref(priv->init_seq);
g_free(priv->nfcid1);
G_OBJECT_CLASS(nfc_tag_t2_parent_class)->finalize(object);
}
Expand Down
2 changes: 0 additions & 2 deletions core/src/nfc_target.c
Expand Up @@ -160,7 +160,6 @@ nfc_target_sequence_dealloc(
g_slice_free(NfcTargetSequence, self);
}

static
NfcTargetSequence*
nfc_target_sequence_ref(
NfcTargetSequence* self)
Expand All @@ -171,7 +170,6 @@ nfc_target_sequence_ref(
return self;
}

static
void
nfc_target_sequence_unref(
NfcTargetSequence* self)
Expand Down

0 comments on commit e47baf1

Please sign in to comment.