From: Olivier Guiter Date: Wed, 26 Sep 2012 08:40:06 +0000 (+0200) Subject: Integrate neard post 0.6 changes - handover code X-Git-Tag: submit/1.0_post/20121012.071401~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d41cea8990dfc8a443da6cc6f67eb8ca3b38f83;p=profile%2Fivi%2Fneard.git Integrate neard post 0.6 changes - handover code --- diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..478653c --- /dev/null +++ b/HACKING @@ -0,0 +1,87 @@ +Hacking on Near Field Communication manager +******************************************* + + +Build tools requirements +======================== + +When building and testing directly from the repository it is important to +have at least automake version 1.10 or later installed. All modern +distributions should default to the latest version, but it seems that +Debian's default is still an earlier version: + + Check version + # dpkg -l '*automake*' + + Install new version + # apt-get install automake1.10 + # update-alternatives --config automake + + +Working with the source code repository +======================================= + +The repository contains two extra scripts that accomplish the bootstrap +process. One is called "bootstrap" which is the basic scripts that uses the +autotools scripts to create the needed files for building and installing. +It makes sure to call the right programs depending on the usage of shared or +static libraries or translations etc. + +The second program is called "bootstrap-configure". This program will make +sure to properly clean the repository, call the "bootstrap" script and then +call configure with proper settings for development. It will use the best +options and pass them over to configure. These options normally include +the enabling the maintainer mode and the debugging features. + +So while in a normal source project the call "./configure ..." is used to +configure the project with its settings like prefix and extra options. In +case of bare repositories call "./bootstrap-configure" and it will bootstrap +the repository and calls configure with all the correct options to make +development easier. + +In case of preparing for a release with "make distcheck", don't use +bootstrap-configure since it could export development specific settings. + +So the normal steps to checkout, build and install such a repository is +like this: + + Checkout repository + # git clone git://git.kernel.org/pub/scm/network/.../neard.git + # cd neard + + Configure and build + # ./bootstrap-configure + # make + + Check installation + # make install DESTDIR=$PWD/x + # find x + # rm -rf x + + Check distribution + # make distcheck + + Final installation + # sudo make install + + Remove autogenerated files + # make maintainer-clean + + +Running from within the source code repository +============================================== + +When using "./configure --enable-maintainer-mode" the automake scripts will +use the plugins directly from within the repository. This removes the need +to use "make install" when testing "neard". The "bootstrap-configure" +automatically includes this option. + + Run daemon in foreground with debugging + # ./src/neard -n -d 'src/*' + +For production installations or distribution packaging it is important that +the "--enable-maintainer-mode" option is NOT used. + +The debugging option -d takes an argument. This argument can be a comma +separated list of file names like 'src/main.c,src/manager.c' to enable debugs +in these files. Simple glob style pattern matching is supported in this list. diff --git a/Makefile.am b/Makefile.am index d39d4e4..e8d0691 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,7 +72,7 @@ EXTRA_DIST = src/genbuiltin $(doc_files) test_scripts = test/disable-adapter test/enable-adapter test/list-adapters \ test/dump-device test/dump-tag test/dump-record \ test/monitor-near test/start-poll test/stop-poll test/write-tag \ - test/push-device + test/push-device test/bt-handover if TEST testdir = $(pkglibdir)/test diff --git a/doc/agent-api.txt b/doc/agent-api.txt new file mode 100644 index 0000000..e1a5330 --- /dev/null +++ b/doc/agent-api.txt @@ -0,0 +1,105 @@ +HandoverAgent hierarchy +======================= + +Service unique name +Interface org.neard.HandoverAgent +Object path freely definable + +Methods dict RequestOOB(dict values) [experimental] + + This method gets called when the service daemon + needs to get Out Of Band data from the handover + agent, typically the BlueZ daemon. + + The service daemon will use this OOB data to build + a Handover Request or Select message and send it to + remote device. + + Values parameter is optional. It should be a dictionary + where the keys are the field names and the values are + the actual fields. If provided it should contain remote + Out Of Band data received in Handover Request message. + Those data will be stored for future use (i.e. when + remote initialize pairing) and providing those will not + initialize pairing. + + The return value should be a dictionary where the + keys are the field names and the values are the + actual fields. + + Possible Errors: org.neard.HandoverAgent.Error.NotSupported + org.neard.HandoverAgent.Error.NoSuchDevice + org.neard.HandoverAgent.Error.InProgress + org.neard.HandoverAgent.Error.Failed + + void PushOOB(dict values) [experimental] + + This method gets called when service daemon received + Handover Select message from selector and needs to pass + remote Out Of Band data to agent to start handover. + + If there is no Bluetooth adapter or if it doesn't + support simple pairing the agent will return an error. + + Agent shall implicitly initialize pairing if needed. + + This function returns when alternative carrier + (Bluetooth) is ready to be used i.e. pairing has + finished. + + Parameter should be a dictionary where the keys are the + field names and the values are the actual fields. + + Possible Errors: org.neard.HandoverAgent.Error.NotSupported + org.neard.HandoverAgent.Error.NoSuchDevice + org.neard.HandoverAgent.Error.InProgress + org.neard.HandoverAgent.Error.Failed + + void Release() [experimental] + + This method gets called when the service daemon + unregisters the agent. An agent can use it to do + cleanup tasks. There is no need to unregister the + agent, because when this method gets called it has + already been unregistered. + +Fields array{byte} EIR + + This is EIR blob. Used by SSP capable devices. + + array{byte} nokia.com:bt + + This is a proprietary extension blob used by some + Nokia Bluetooth 2.0 devices. + + +NDEFAgent hierarchy +======================= + +Service unique name +Interface org.neard.NDEFAgent +Object path freely definable + +Methods dict GetNDEF(dict values) [experimental] + + This method gets called when the service daemon + found an NDEF matching the registered type. + + The parameter is a dictionary where the keys are the + field names and the values are the actual fields. + + void Release() [experimental] + + This method gets called when the service daemon + unregisters the agent. An agent can use it to do + cleanup tasks. There is no need to unregister the + agent, because when this method gets called it has + already been unregistered. + +Fields array{byte} NDEF + + This is the raw NDEF data. + + object Record + + This is a record object path. diff --git a/doc/coding-style.txt b/doc/coding-style.txt new file mode 100644 index 0000000..47f9c4a --- /dev/null +++ b/doc/coding-style.txt @@ -0,0 +1,344 @@ +Every project has its coding style, and neard is not an exception. This +document describes the preferred coding style for neard code, in order to keep +some level of consistency among developers so that code can be easily +understood and maintained, and also to help your code survive under +maintainer's fastidious eyes so that you can get a passport for your patch +ASAP. + +First of all, neard coding style must follow every rule for Linux kernel +(http://www.kernel.org/doc/Documentation/CodingStyle). There also exists a tool +named checkpatch.pl to help you check the compliance with it. Just type +"checkpatch.pl --no-tree patch_name" to check your patch. In theory, you need +to clean up all the warnings and errors except this one: "ERROR: Missing +Signed-off-by: line(s)". neard does not used Signed-Off lines, so including +them is actually an error. In certain circumstances one can ignore the 80 +character per line limit. This is generally only allowed if the alternative +would make the code even less readable. + +Besides the kernel coding style above, neard has special flavors for its own. +Some of them are mandatory (marked as 'M'), while some others are optional +(marked as 'O'), but generally preferred. + +M1: Blank line before and after an if/while/do/for statement +============================================================ +There should be a blank line before if statement unless the if is nested and +not preceded by an expression or variable declaration. + +Example: +1) +a = 1; +if (b) { // wrong + +2) +a = 1 + +if (b) { +} +a = 2; // wrong + +3) +if (a) { + if (b) // correct + +4) +b = 2; + +if (a) { // correct + +} + +b = 3; + +The only exception to this rule applies when a variable is being allocated: +array = g_try_new0(int, 20); +if (array == NULL) // Correct + return; + + +M2: Multiple line comment +========================= +If your comments have more then one line, please start it from the second line. + +Example: +/* + * first line comment // correct + * ... + * last line comment + */ + + +M3: Space before and after operator +=================================== +There should be a space before and after each operator. + +Example: +a + b; // correct + + +M4: Wrap long lines +=================== +If your condition in if, while, for statement or a function declaration is too +long to fit in one line, the new line needs to be indented not aligned with the +body. + +Example: +1) +if (call->status == CALL_STATUS_ACTIVE || + call->status == CALL_STATUS_HELD) { // wrong + neard_dbus_dict_append(); + +2) +if (call->status == CALL_STATUS_ACTIVE || + call->status == CALL_STATUS_HELD) { // correct + neard_dbus_dict_append(); + +3) +gboolean sim_ust_is_available(unsigned char *service_ust, unsigned char len, + num sim_ust_service index) // wrong +{ + int a; + ... +} + +4) +gboolean sim_ust_is_available(unsigned char *service_ust, unsigned char len, + enum sim_ust_service index) // correct +{ + int a; + ... +} + +If the line being wrapped is a function call or function declaration, the +preferred style is to indent at least past the opening parenthesis. Indenting +further is acceptable as well (as long as you don't hit the 80 character +limit). + +If this is not possible due to hitting the 80 character limit, then indenting +as far as possible to the right without hitting the limit is preferred. + +Example: + +1) +gboolean sim_ust_is_available(unsigned char *service_ust, unsigned char len, + enum sim_ust_service index); // worse + +2) +gboolean sim_ust_is_available(unsigned char *service_ust, unsigned char len, + enum sim_ust_service index); + // better + +M5: Git commit message 50/72 formatting +======================================= +The commit message header should be within 50 characters. And if you have +detailed explanatory text, wrap it to 72 character. + + +M6: Space when doing type casting +================================= +There should be a space between new type and variable. + +Example: +1) +a = (int *)b; // wrong +2) +a = (int *) b; // correct + + +M7: Don't initialize variable unnecessarily +=========================================== +When declaring a variable, try not to initialize it unless necessary. + +Example: +int i = 1; // wrong + +for (i = 0; i < 3; i++) { +} + + +M8: Use g_try_malloc instead of g_malloc +======================================== +When g_malloc fails, the whole program would exit. Most of time, this is not +the expected behavior, and you may want to use g_try_malloc instead. + +Example: +additional = g_try_malloc(len - 1); // correct +if (additional == NULL) + return FALSE; + + +M9: Follow the order of include header elements +=============================================== +When writing an include header the various elements should be in the following +order: + - #includes + - forward declarations + - #defines + - enums + - typedefs + - function declarations and inline function definitions + + +M10: Internal headers must not use include guards +================================================= +Any time when creating a new header file with non-public API, that header +must not contain include guards. + + +M11: Naming of enums +==================== + +Enums must have a descriptive name. The enum type should be small caps and +it should not be typedef-ed. Enum contents should be in CAPITAL letters and +prefixed by the enum type name. + +Example: + +enum animal_type { + ANIMAL_TYPE_FOUR_LEGS, + ANIMAL_TYPE_EIGHT_LEGS, + ANIMAL_TYPE_TWO_LEGS, +}; + +If the enum contents have values (e.g. from specification) the formatting +should be as follows: + +enum animal_type { + ANIMAL_TYPE_FOUR_LEGS = 4, + ANIMAL_TYPE_EIGHT_LEGS = 8, + ANIMAL_TYPE_TWO_LEGS = 2, +}; + +M12: Enum as switch variable +==================== + +If the variable of a switch is an enum, you must not include a default in +switch body. The reason for this is: If later on you modify the enum by adding +a new type, and forget to change the switch accordingly, the compiler will +complain the new added type hasn't been handled. + +Example: + +enum animal_type { + ANIMAL_TYPE_FOUR_LEGS = 4, + ANIMAL_TYPE_EIGHT_LEGS = 8, + ANIMAL_TYPE_TWO_LEGS = 2, +}; + +enum animal_type t; + +switch (t) { +case ANIMAL_TYPE_FOUR_LEGS: + ... + break; +case ANIMAL_TYPE_EIGHT_LEGS: + ... + break; +case ANIMAL_TYPE_TWO_LEGS: + ... + break; +default: // wrong + break; +} + +However if the enum comes from an external header file outside neard +we cannot make any assumption of how the enum is defined and this +rule might not apply. + +M13: Check for pointer being NULL +================================= + +When checking if a pointer or a return value is NULL, explicitly compare to +NULL rather than use the shorter check with "!" operator. + +Example: +1) +array = g_try_new0(int, 20); +if (!array) // Wrong + return; + +2) +if (!g_at_chat_get_slave(chat)) // Wrong + return -EINVAL; + +3) +array = g_try_new0(int, 20); +if (array == NULL) // Correct + return; + + +M14: Always use parenthesis with sizeof +======================================= +The expression argument to the sizeof operator should always be in +parenthesis, too. + +Example: +1) +memset(stuff, 0, sizeof(*stuff)); + +2) +memset(stuff, 0, sizeof *stuff); // Wrong + + +M15: Use void if function has no parameters +=========================================================== +A function with no parameters must use void in the parameter list. + +Example: +1) +void foo(void) +{ +} + +2) +void foo() // Wrong +{ +} + +M16: Don't use hex value with shift operators +============================================== +The expression argument to the shift operators should not be in hex. + +Example: + +1) +1 << y + +2) +0x1 << y // Wrong + +O1: Shorten the name +==================== +Better to use abbreviation, rather than full name, to name a variable, +function, struct, etc. + +Example: +supplementary_service // too long +ss // better + +O2: Try to avoid complex if body +================================ +It's better not to have a complicated statement for if. You may judge its +contrary condition and return | break | continue | goto ASAP. + +Example: +1) +if (a) { // worse + struct voicecall *v; + call = synthesize_outgoing_call(vc, vc->pending); + v = voicecall_create(vc, call); + v->detect_time = time(NULL); + DBG("Registering new call: %d", call->id); + voicecall_dbus_register(v); +} else + return; + +2) +if (!a) + return; + +struct voicecall *v; +call = synthesize_outgoing_call(vc, vc->pending); +v = voicecall_create(vc, call); +v->detect_time = time(NULL); +DBG("Registering new call: %d", call->id); +voicecall_dbus_register(v); diff --git a/doc/features.txt b/doc/features.txt new file mode 100644 index 0000000..5745dc0 --- /dev/null +++ b/doc/features.txt @@ -0,0 +1,45 @@ +neard - Near Field Communication daemon +======================================= + +Purpose +======= + +This document describes all the major functionalities +supported by neard. + + +Reader Mode +=========== +Supported tags: + + * Type 1: Supported. + * Type 2: Supported. + * MIFARE classic 1K and 4K supported. + * Type 3: Supported. + * Type 4: Supported. + + +Card Emulation Mode +=================== +Not supported. + + +Writer Mode +=========== +Supported tags: + + * Type 1: Supported. + * Type 2: Supported. + * Type 3: Supported. + * Type 4: Supported. + + +Peer To Peer Mode +================= +neard reads and write NDEFs from p2p devices, through SNEP and NPP. +Both initiator and target modes are supported. + + +Handover +======== +WIP. diff --git a/gdbus/object.c b/gdbus/object.c index 900e7ab..9689006 100644 --- a/gdbus/object.c +++ b/gdbus/object.c @@ -645,8 +645,8 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn, goto fail; if (g_dbus_args_have_signature(args, signal) == FALSE) { - error("%s.%s: expected signature'%s' but got '%s'", - interface, name, args, signature); + error("%s.%s: got unexpected signature '%s'", interface, name, + dbus_message_get_signature(signal)); ret = FALSE; goto fail; } diff --git a/plugins/handover.c b/plugins/handover.c index 8ba550a..c8ba895 100644 --- a/plugins/handover.c +++ b/plugins/handover.c @@ -90,6 +90,7 @@ static void free_hr_ndef(gpointer data) if (ndef != NULL) g_free(ndef->ndef); + g_free(ndef); } @@ -134,7 +135,7 @@ static int handover_ndef_parse(int client_fd, struct hr_ndef *ndef) * exchange with a Hr), so we have to do some actions (e.g.: * pairing with bluetooth) */ - if (strncmp((char *)(ndef->ndef + FRAME_TYPE_OFFSET), "Hr", 2) == 0) { + if (strncmp((char *) (ndef->ndef + FRAME_TYPE_OFFSET), "Hr", 2) == 0) { /* * The first entry on the record list is the Hr record. * We build the Hs based on it. @@ -158,7 +159,7 @@ static int handover_ndef_parse(int client_fd, struct hr_ndef *ndef) return err; fail: - near_error("ndef parsing failed (%d)", err); + near_error("ndef parsing failed %d", err); handover_close(client_fd, 0); @@ -186,7 +187,7 @@ static near_bool_t handover_read_cfg_records(int client_fd, ndef = g_hash_table_lookup(hr_ndef_hash, GINT_TO_POINTER(client_fd)); if (ndef == NULL) { - near_error("hr_ndef should exist !!!"); + near_error("hr_ndef should exist"); return FALSE; } @@ -375,7 +376,7 @@ static near_bool_t handover_read(int client_fd, ndef = g_hash_table_lookup(hr_ndef_hash, GINT_TO_POINTER(client_fd)); if (ndef == NULL) { - /* First call: allocate and read header bytes*/ + /* First call: allocate and read header bytes */ return handover_read_initialize(client_fd, adapter_idx, target_idx, cb); } @@ -408,7 +409,7 @@ static gboolean handover_push_event(GIOChannel *channel, GIOCondition condition, gpointer data) { near_bool_t ret; - struct hr_push_client *client = (struct hr_push_client *)data; + struct hr_push_client *client = (struct hr_push_client *) data; DBG("condition 0x%x", condition); @@ -467,6 +468,7 @@ static int handover_push(int client_fd, struct near_p2p_driver handover_driver = { .name = "Handover", .service_name = NEAR_DEVICE_SN_HANDOVER, + .fallback_service_name = NEAR_DEVICE_SN_SNEP, .read = handover_read, .push = handover_push, .close = handover_close, diff --git a/plugins/mifare.c b/plugins/mifare.c index db71536..72120fe 100644 --- a/plugins/mifare.c +++ b/plugins/mifare.c @@ -39,28 +39,37 @@ #include #include -/* NXP Application Notes: +/* + * NXP Application Notes: * AN1304, AN1305, ... * http://www.nxp.com/technical-support-portal/53420/71108/application-notes - * */ + */ -/* Prototype */ +/* Prototypes */ int mifare_read(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); +int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); + +int mifare_write(uint32_t adapter_idx, uint32_t target_idx, + struct near_ndef_message *ndef, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); + /* MIFARE command set */ -#define MF_CMD_WRITE 0xA2 +#define MF_CMD_WRITE 0xA0 #define MF_CMD_READ 0x30 #define MF_CMD_AUTH_KEY_A 0x60 #define NFC_AID_TAG 0xE103 -/* Define boundaries for 1K / 2K / 4K +/* + * Define boundaries for 1K / 2K / 4K * 1K: sector 0 to 15 (3 blocks each + trailer block ) * 2K: sector 0 to 31 (3 blocks each + trailer block ) * 4K: sector 0 to 31 (3 blocks each + trailer block ) * and sector 32 to 39 (15 blocks each + trailer block ) - * */ + */ #define DEFAULT_BLOCK_SIZE 16 /* MF_CMD_READ */ #define STD_BLK_SECT_TRAILER 4 /* bl per sect with trailer 1K/2K */ @@ -93,12 +102,14 @@ static uint8_t MAD_NFC_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; #define MAD1_1ST_BLOCK 0x00 /* 1st block of sector 0 */ #define MAD2_GPB_BITS 0x02 /* MAD v2 flag */ -#define MAD2_SECTOR 0x10 /* Sector 0 is for MAD2 */ +#define MAD2_SECTOR 0x10 /* Sector 16 is for MAD2 */ #define MAD2_1ST_BLOCK 0x40 /* 1st block of MAD2 */ #define MAD_V1_AIDS_LEN 15 /* 1 to 0x0F */ #define MAD_V2_AIDS_LEN 23 /*0x11 to 0x27 */ +#define NFC_1ST_BLOCK 0x04 /* Sectors from 1 are for NFC */ + /* MAD1 sector structure. Start at block 0x00 */ struct MAD_1 { uint8_t man_info[16]; @@ -131,22 +142,30 @@ struct mifare_cookie { struct near_tag *tag; near_tag_io_cb cb; near_recv next_far_func; + int (*command)(void *data); /* read or write after unlocking sector */ /* For MAD access */ struct MAD_1 *mad_1; struct MAD_2 *mad_2; GSList *g_sect_list; /* Global sectors list */ - /* For read functions */ - near_recv rs_next_fct; /* next function */ - int rs_block_start; /* first block */ - int rs_block_end; /* last block */ - int rs_completed; /* read blocks */ + /* For read and write functions */ + near_recv rws_next_fct; /* next function */ + int rws_block_start; /* first block */ + int rws_block_end; /* last block */ + int rws_completed; /* read blocks */ + + + /* For read only */ int rs_length; /* read length */ uint8_t *rs_pmem; /* Stored read sector */ int rs_max_length; /* available size */ uint8_t *nfc_data; size_t nfc_data_length; + + /* For write only */ + struct near_ndef_message *ndef; /* message to write */ + size_t ndef_length; /* message length */ }; struct type2_cmd { @@ -155,6 +174,12 @@ struct type2_cmd { uint8_t data[]; } __attribute__((packed)); +struct mf_write_cmd { + uint8_t cmd; + uint8_t block; + uint8_t data[DEFAULT_BLOCK_SIZE]; +} __attribute__((packed)); + struct mifare_cmd { uint8_t cmd; uint8_t block; @@ -162,9 +187,10 @@ struct mifare_cmd { uint8_t nfcid[NFC_NFCID1_MAXSIZE]; } __attribute__((packed)); -/* Common free func */ -static int mifare_release(int err, struct mifare_cookie *cookie) +static int mifare_release(int err, void *data) { + struct mifare_cookie *cookie = data; + DBG("%p", cookie); if (cookie == NULL) @@ -180,13 +206,19 @@ static int mifare_release(int err, struct mifare_cookie *cookie) g_slist_free(cookie->g_sect_list); g_free(cookie->mad_1); g_free(cookie->mad_2); + + if (cookie->ndef) + g_free(cookie->ndef->data); + + g_free(cookie->ndef); g_free(cookie); cookie = NULL; return err; } -/* Mifare_generic MAD unlock block function +/* + * Mifare_generic MAD unlock block function * This function send unlock code to the tag, and so, allow access * to the complete related sector. */ @@ -198,9 +230,10 @@ static int mifare_unlock_sector(int block_id, struct mifare_cookie *cookie = data; uint8_t *key_ref; - /* For MADs sectors we use public key A (a0a1a2a3a4a5) but - * for NFC sectors we use NFC_KEY_A (d3f7d3f7d3f7) - * */ + /* + * For MADs sectors we use public key A (a0a1a2a3a4a5) but +- * for NFC sectors we use NFC_KEY_A (d3f7d3f7d3f7) + */ if ((block_id == MAD1_1ST_BLOCK) || (block_id == MAD2_1ST_BLOCK)) key_ref = MAD_public_key; else @@ -209,7 +242,7 @@ static int mifare_unlock_sector(int block_id, /* CMD AUTHENTICATION */ cmd.cmd = MF_CMD_AUTH_KEY_A; - /* We want to authenticate the 1st bloc of the sector */ + /* Authenticate will be on the 1st block of the sector */ cmd.block = block_id; /* Store the AUTH KEY */ @@ -224,13 +257,15 @@ static int mifare_unlock_sector(int block_id, cookie); } -/* Common MIFARE Bloc read: +/* + * Common MIFARE Block read: * Each call will read 16 bytes from tag... so to read 1 sector, - * we must call it 4 times or 16 times (minus 1 or not for the trailer block) + * it has to be called it 4 times or 16 times + * (minus 1 or not for the trailer block) * * data: mifare_cookie *mf_ck * mf_ck->read_block: block number to read - * */ + */ static int mifare_read_block(uint8_t block_id, void *data, near_recv far_func) @@ -262,21 +297,22 @@ static int mifare_read_sector_cb(uint8_t *resp, int length, void *data) /* save the length: */ mf_ck->rs_length = mf_ck->rs_length + length; - memcpy(mf_ck->rs_pmem + mf_ck->rs_completed * DEFAULT_BLOCK_SIZE, + memcpy(mf_ck->rs_pmem + mf_ck->rws_completed * DEFAULT_BLOCK_SIZE, resp + 1,/* ignore reader byte */ length); /* Next block */ - mf_ck->rs_completed = mf_ck->rs_completed + 1; + mf_ck->rws_completed = mf_ck->rws_completed + 1; - if ((mf_ck->rs_block_start + mf_ck->rs_completed) < mf_ck->rs_block_end) + if ((mf_ck->rws_block_start + mf_ck->rws_completed) + < mf_ck->rws_block_end) err = mifare_read_block( - (mf_ck->rs_block_start + mf_ck->rs_completed), + (mf_ck->rws_block_start + mf_ck->rws_completed), data, mifare_read_sector_cb); else { /* Now Process the callback ! */ - err = (*mf_ck->rs_next_fct)(mf_ck->rs_pmem, + err = (*mf_ck->rws_next_fct)(mf_ck->rs_pmem, mf_ck->rs_length, data); } @@ -298,7 +334,7 @@ static int mifare_read_sector_unlocked(uint8_t *resp, int length, void *data) return err; } /* And run the read process on the first block of the sector */ - err = mifare_read_block(mf_ck->rs_block_start, data, + err = mifare_read_block(mf_ck->rws_block_start, data, mifare_read_sector_cb); if (err < 0) @@ -309,7 +345,8 @@ out_err: return err; } -/* This function reads a complete sector, using block per block function. +/* + * This function reads a complete sector, using block per block function. * sector sizes can be: * Sectors 0 to 31: * 48 bytes: 3*16 no trailer @@ -337,13 +374,13 @@ static int mifare_read_sector(void *cookie, mf_ck->rs_pmem = pmem; /* where to store */ mf_ck->rs_max_length = memsize; /* max size to store */ mf_ck->rs_length = 0; /* no bytes yet */ - mf_ck->rs_completed = 0; /* blocks read */ + mf_ck->rws_completed = 0; /* blocks read */ /* According to tag size, compute the correct block offset */ if (sector_id < T4K_BOUNDARY) - mf_ck->rs_block_start = sector_id * 4; /* 1st block to read */ + mf_ck->rws_block_start = sector_id * 4; /* 1st block to read */ else - mf_ck->rs_block_start = + mf_ck->rws_block_start = (sector_id - T4K_BOUNDARY) * 16 + T4K_BLK_OFF; /* Find blocks_per_sect, according to position and trailer or not */ @@ -352,12 +389,12 @@ static int mifare_read_sector(void *cookie, else blocks_count = (EXT_BLK_PER_SECT + trailer); - mf_ck->rs_block_end = mf_ck->rs_block_start + blocks_count; + mf_ck->rws_block_end = mf_ck->rws_block_start + blocks_count; - mf_ck->rs_next_fct = next_func; /* leaving function */ + mf_ck->rws_next_fct = next_func; /* leaving function */ - /* As we are on the first block of a sector, we unlock it */ - err = mifare_unlock_sector(mf_ck->rs_block_start, + /* Being on the first block of a sector, unlock it */ + err = mifare_unlock_sector(mf_ck->rws_block_start, mifare_read_sector_unlocked, mf_ck); return err; @@ -403,7 +440,7 @@ static int mifare_read_NFC_loop(uint8_t *resp, int length, void *data) uint8_t *nfc_data; size_t nfc_data_length; - DBG("READ DONE"); + DBG("Done reading"); nfc_data = near_tag_get_data(mf_ck->tag, &nfc_data_length); if (nfc_data == NULL) { @@ -421,8 +458,7 @@ out_err: return mifare_release(err, mf_ck); } -/* Prepare read NFC loop - */ +/* Prepare read NFC loop */ static int mifare_read_NFC(void *data) { struct mifare_cookie *mf_ck = data; @@ -510,8 +546,8 @@ done_mad: goto out_err; } - /* Time to read the NFC data */ - err = mifare_read_NFC(mf_ck); + /* Time to read or write the NFC data */ + err = mf_ck->command(mf_ck); return err; @@ -519,15 +555,13 @@ out_err: return mifare_release(err, mf_ck); } -/* Transitional function - async - */ +/* Transitional function - async */ static int read_MAD2_complete(uint8_t *empty, int iempty, void *data) { return mifare_process_MADs(data); } -/* This function reads the MAD2 sector - */ +/* This function reads the MAD2 sector */ static int mifare_read_MAD2(void *data) { struct mifare_cookie *mf_ck = data; @@ -535,7 +569,7 @@ static int mifare_read_MAD2(void *data) DBG(""); - /* As auth is ok, we allocate Mifare Access Directory v1 */ + /* As auth is ok, allocate Mifare Access Directory v1 */ mf_ck->mad_2 = g_try_malloc0(STD_SECTOR_SIZE); if (mf_ck->mad_2 == NULL) { near_error("Memory allocation failed (MAD2)"); @@ -558,10 +592,10 @@ out_err: return mifare_release(err, mf_ck); } -/* This function checks, in MAD1, if there's a MAD2 directory +/* + * This function checks, in MAD1, if there's a MAD2 directory * available. This is is the case for 2K and 4K tag - * If MAD2 exists, we want to read it, elsewhere we process the - * current MAD + * If MAD2 exists, read it, elsewhere process the current MAD */ static int read_MAD1_complete(uint8_t *empty, int iempty, void *data) { @@ -570,7 +604,7 @@ static int read_MAD1_complete(uint8_t *empty, int iempty, void *data) DBG(""); - /* Check if we need to get MAD2 sector (bits 0..1)*/ + /* Check if there's a need to get MAD2 sector */ if ((mf_ck->mad_1->GPB & 0x03) == MAD2_GPB_BITS) err = mifare_read_MAD2(mf_ck); else @@ -579,7 +613,8 @@ static int read_MAD1_complete(uint8_t *empty, int iempty, void *data) return err; } -/* Function called to read the first MAD sector +/* + * Function called to read the first MAD sector * MAD is mandatory */ static int mifare_read_MAD1(uint8_t *resp, int length, void *data) @@ -594,8 +629,10 @@ static int mifare_read_MAD1(uint8_t *resp, int length, void *data) return err; } - /* As auth is ok, we allocate Mifare Access Directory v1 - * allocated size is also STD_SECTOR_SIZE */ + /* + * As auth is ok, allocate Mifare Access Directory v1 + * allocated size is also STD_SECTOR_SIZE + */ mf_ck->mad_1 = g_try_malloc0(STD_SECTOR_SIZE); if (mf_ck->mad_1 == NULL) { near_error("Memory allocation failed (MAD1)"); @@ -619,12 +656,13 @@ out_err: return mifare_release(err, mf_ck); } -/* MIFARE: entry point: +/* + * MIFARE: entry point: * Read all the MAD sectors (0x00, 0x10) to get the Application Directory * entries. * On sector 0x00, App. directory is on block 0x01 & block 0x02 * On sector 0x10, App. directory is on block 0x40, 0x41 & 0x42 - * On reading, we ignore the CRC. + * On reading, CRC is ignored. */ int mifare_read(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype) @@ -655,11 +693,13 @@ int mifare_read(uint32_t adapter_idx, uint32_t target_idx, cookie->adapter_idx = adapter_idx; cookie->target_idx = target_idx; cookie->cb = cb; + cookie->command = mifare_read_NFC; - /* Need to unlock before reading + /* + * Need to unlock before reading * This will check if public keys are allowed (and, so, NDEF could * be "readable"... - * */ + */ err = mifare_unlock_sector(MAD1_1ST_BLOCK, /* related block */ mifare_read_MAD1, /* callback function */ cookie); /* target data */ @@ -668,3 +708,348 @@ int mifare_read(uint32_t adapter_idx, uint32_t target_idx, return 0; } + +static int check_presence(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *cookie = data; + int err = 0; + + DBG("%d", length); + + if (length < 0) + err = -EIO; + + if (cookie->cb) + cookie->cb(cookie->adapter_idx, cookie->target_idx, err); + + return err; +} + +int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype) +{ + struct mifare_cmd cmd; + struct mifare_cookie *cookie; + uint8_t *key_ref = MAD_public_key; + int err; + + DBG(""); + + /* Check supported and tested Mifare type */ + switch (tgt_subtype) { + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K: + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K: + break; + default: + near_error("Mifare tag type %d not supported.", tgt_subtype); + return -1; + } + + /* Alloc global cookie */ + cookie = g_try_malloc0(sizeof(struct mifare_cookie)); + if (cookie == NULL) + return -ENOMEM; + + /* Get the nfcid1 */ + cookie->nfcid1 = near_tag_get_nfcid(adapter_idx, target_idx, + &cookie->nfcid1_len); + cookie->adapter_idx = adapter_idx; + cookie->target_idx = target_idx; + cookie->cb = cb; + + /* + * To check presence of Mifare Classic Tag, + * send authentication command instead of read one + */ + cmd.cmd = MF_CMD_AUTH_KEY_A; + + /* Authenticate the 1st block of the MAD sector */ + cmd.block = MAD1_1ST_BLOCK; + + /* Store the AUTH KEY */ + memcpy(&cmd.key, key_ref, MAD_KEY_LEN); + + /* add the UID */ + memcpy(&cmd.nfcid, cookie->nfcid1, cookie->nfcid1_len); + + err = near_adapter_send(cookie->adapter_idx, + (uint8_t *) &cmd, + sizeof(cmd) - NFC_NFCID1_MAXSIZE + cookie->nfcid1_len, + check_presence, + cookie); + + if (err < 0) + goto out_err; + + return err; + +out_err: + mifare_release(err, cookie); + + return err; +} + +/* + * Common MIFARE Block write: + * Each call will write 16 bytes to tag... so to write 1 sector, + * it has to be called it 4 or 16 times (minus 1 for the trailer block) + */ +static int mifare_write_block(uint8_t block_id, void *data, + near_recv far_func) +{ + struct mf_write_cmd cmd; + struct mifare_cookie *mf_ck = data; + + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = MF_CMD_WRITE; /* MIFARE WRITE */ + cmd.block = block_id; + + if ((mf_ck->ndef->offset + DEFAULT_BLOCK_SIZE) < + mf_ck->ndef->length) { + memcpy(cmd.data, mf_ck->ndef->data + + mf_ck->ndef->offset, DEFAULT_BLOCK_SIZE); + mf_ck->ndef->offset += DEFAULT_BLOCK_SIZE; + } else { + memcpy(cmd.data, mf_ck->ndef->data + mf_ck->ndef->offset, + mf_ck->ndef->length - mf_ck->ndef->offset); + mf_ck->ndef->offset = mf_ck->ndef->length + 1; + } + + return near_adapter_send(mf_ck->adapter_idx, + (uint8_t *) &cmd, sizeof(cmd), + far_func, data); +} + +static int mifare_correct_length_cb(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *mf_ck = data; + + DBG("Done writing"); + + if (mf_ck->cb) + mf_ck->cb(mf_ck->adapter_idx, mf_ck->target_idx, 0); + + return mifare_release(0, mf_ck); +} + +/* After writing ndef message, its length has to be updated */ +static int mifare_correct_length(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *mf_ck = data; + + DBG(""); + + /* Correct length field */ + mf_ck->ndef->data[1] = mf_ck->ndef_length; + /* and ndef offset so it points to the beginning */ + mf_ck->ndef->offset = 0; + + /* Run the write process only on the first block of the sector */ + return mifare_write_block(NFC_1ST_BLOCK, mf_ck, + mifare_correct_length_cb); +} + +static int mifare_write_sector_cb(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *mf_ck = data; + int err; + + /* Next block */ + mf_ck->rws_completed = mf_ck->rws_completed + 1; + + /* Check if it's the last block */ + if ((mf_ck->rws_block_start + mf_ck->rws_completed) + < mf_ck->rws_block_end) { + /* then check if there's still data to write */ + if (mf_ck->ndef->offset < mf_ck->ndef->length) + err = mifare_write_block( + mf_ck->rws_block_start + mf_ck->rws_completed, + data, mifare_write_sector_cb); + else + /* No more Data to write */ + /* Correct length of the ndef message */ + err = mifare_unlock_sector(NFC_1ST_BLOCK, + mifare_correct_length, mf_ck); + } else { + /* Process the callback */ + err = (*mf_ck->rws_next_fct)(resp, length, data); + } + + if (err < 0) + return mifare_release(err, mf_ck); + + return err; + +} + +static int mifare_write_sector_unlocked(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *mf_ck = data; + + /* Run the write process on the first block of the sector */ + return mifare_write_block(mf_ck->rws_block_start, data, + mifare_write_sector_cb); +} + +/* + * This function writes a complete sector, using block per block function. + * sector sizes can be: + * Sectors 0 to 31: + * 48 bytes: 3*16 (no trailer) + * Sectors 32 to 39: + * 240 bytes: 15*16 (no trailer) + * + * Unlock is done at the beginning of each sector. + */ +static int mifare_write_sector(void *cookie, + uint8_t sector_id, /* sector to write */ + near_recv next_func) +{ + struct mifare_cookie *mf_ck = cookie; + int blocks_count; + + DBG(""); + + /* Prepare call values */ + + /* According to tag size, compute the correct block offset */ + if (sector_id < T4K_BOUNDARY) + mf_ck->rws_block_start = sector_id * STD_BLK_SECT_TRAILER; + else + mf_ck->rws_block_start = T4K_BLK_OFF + + (sector_id - T4K_BOUNDARY) * EXT_BLK_SECT_TRAILER; + + /* Find blocks_per_sect, according to position, no trailer */ + if (sector_id < T4K_BOUNDARY) + blocks_count = STD_BLK_PER_SECT; + else + blocks_count = EXT_BLK_PER_SECT; + + mf_ck->rws_block_end = mf_ck->rws_block_start + blocks_count; + mf_ck->rws_completed = 0; + mf_ck->rws_next_fct = next_func; + + /* Being on the first block of the sector, unlock it */ + return mifare_unlock_sector(mf_ck->rws_block_start, + mifare_write_sector_unlocked, mf_ck); +} + +static int mifare_write_NFC_loop(uint8_t *resp, int length, void *data) +{ + struct mifare_cookie *mf_ck = data; + int err = 0; + + if (length < 0 || resp[0] != 0) { + err = -EIO; + goto out_err; + } + + /* Something more to write? */; + if (mf_ck->ndef->offset < mf_ck->ndef->length) { + err = mifare_write_sector(data, /* cookie */ + GPOINTER_TO_INT(mf_ck->g_sect_list->data), + mifare_write_NFC_loop); /* next function */ + + mf_ck->g_sect_list = g_slist_remove(mf_ck->g_sect_list, + mf_ck->g_sect_list->data); + + if (err < 0) + goto out_err; + + } else { + /* Correct length of an NDEF message */ + err = mifare_unlock_sector(NFC_1ST_BLOCK, + mifare_correct_length, mf_ck); + + if (err < 0) + goto out_err; + } + + return err; +out_err: + return mifare_release(err, mf_ck); +} + +static int mifare_write_NFC(void *data) +{ + struct mifare_cookie *mf_ck = data; + int err; + + DBG(""); + + mf_ck->rws_completed = 0; /* written blocks */ + + /* First write here: */ + err = mifare_write_sector(data, /* cookie */ + GPOINTER_TO_INT(mf_ck->g_sect_list->data), /* sector id */ + mifare_write_NFC_loop); /* next function */ + + mf_ck->g_sect_list = g_slist_remove(mf_ck->g_sect_list, + mf_ck->g_sect_list->data); + + if (err < 0) + return mifare_release(err, mf_ck); + + return err; +} + +int mifare_write(uint32_t adapter_idx, uint32_t target_idx, + struct near_ndef_message *ndef, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype) +{ + struct mifare_cookie *cookie; + struct near_tag *tag; + size_t tag_size; + int err; + + DBG(""); + + /* Check supported and tested Mifare type */ + switch (tgt_subtype) { + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K: + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K: + break; + default: + near_error("Mifare tag type %d not supported.", tgt_subtype); + return -1; + } + + /* Check if there's enough space on tag */ + tag = near_tag_get_tag(adapter_idx, target_idx); + near_tag_get_data(tag, &tag_size); + + if (tag_size < ndef->length) { + near_error("Not enough space on tag"); + return -ENOSPC; + } + + /* Alloc global cookie */ + cookie = g_try_malloc0(sizeof(struct mifare_cookie)); + if (cookie == NULL) + return -ENOMEM; + + /* Get the nfcid1 */ + cookie->nfcid1 = near_tag_get_nfcid(adapter_idx, target_idx, + &cookie->nfcid1_len); + cookie->adapter_idx = adapter_idx; + cookie->target_idx = target_idx; + cookie->cb = cb; + + cookie->command = mifare_write_NFC; + cookie->ndef = ndef; + /* Save ndef length */ + cookie->ndef_length = cookie->ndef->data[1]; + cookie->ndef->data[1] = 0; + /* + * Mifare Classic Tag needs to be unlocked before writing + * This will check if public keys are allowed (NDEF could be "readable") + */ + err = mifare_unlock_sector(MAD1_1ST_BLOCK, /* related block */ + mifare_read_MAD1, /* callback */ + cookie); /* target data */ + + if (err < 0) + return mifare_release(err, cookie); + + return 0; +} diff --git a/plugins/nfctype1.c b/plugins/nfctype1.c index 4b78a35..4042429 100644 --- a/plugins/nfctype1.c +++ b/plugins/nfctype1.c @@ -119,10 +119,14 @@ static void t1_init_cmd(struct type1_tag *tag, struct type1_cmd *cmd) memcpy(cmd->uid, tag->uid, UID_LENGTH); } -static void t1_cookie_release(struct t1_cookie *cookie) +static int t1_cookie_release(int err, void *data) { + struct t1_cookie *cookie = data; + + DBG("%p", cookie); + if (cookie == NULL) - return; + return err; if (cookie->ndef) g_free(cookie->ndef->data); @@ -130,10 +134,12 @@ static void t1_cookie_release(struct t1_cookie *cookie) g_free(cookie->ndef); g_free(cookie); cookie = NULL; + + return err; } -/* Read segments (128 bytes)and store them to the tag data block */ -static int segment_read_recv(uint8_t *resp, int length, void *data) +/* Read segments (128 bytes) and store them to the tag data block */ +static int data_recv(uint8_t *resp, int length, void *data) { struct type1_tag *t1_tag = data; struct type1_cmd t1_cmd; @@ -151,9 +157,9 @@ static int segment_read_recv(uint8_t *resp, int length, void *data) length = length - LEN_STATUS_BYTE; /* ignore first byte */ - /* Add data to tag mem*/ + /* Add data to tag mem */ tagdata = near_tag_get_data(t1_tag->tag, &data_length); - memcpy(tagdata + t1_tag->data_read, resp+1, length); + memcpy(tagdata + t1_tag->data_read, resp + 1, length); /* Next segment */ t1_tag->data_read = t1_tag->data_read + length; @@ -167,8 +173,8 @@ static int segment_read_recv(uint8_t *resp, int length, void *data) t1_cmd.addr = (t1_tag->current_seg << 4) & 0xFF; err = near_adapter_send(t1_tag->adapter_idx, - (uint8_t *)&t1_cmd, sizeof(t1_cmd), - segment_read_recv, t1_tag); + (uint8_t *) &t1_cmd, sizeof(t1_cmd), + data_recv, t1_tag); if (err < 0) goto out_err; } else { /* This is the end */ @@ -189,7 +195,8 @@ out_err: return err; } -/* The dynamic read function: +/* + * The dynamic read function: * Bytes [0..3] : CC * [4..8]: TLV Lock ControlIT (0x01, 0x03, v1, V2, V3) * [9..13]: TLV Reserved Memory Control (0x02, 0x03, V1, V2, V3) @@ -213,9 +220,10 @@ static int read_dynamic_tag(uint8_t *cc, int length, void *data) pndef = pndef + 5; /* skip TLV Lock bits bytes */ pndef = pndef + 5; /* skip TLV ControlIT bytes */ - /* Save first NFC bytes to tag memory + /* + * Save first NFC bytes to tag memory * 10 blocks[0x3..0xC] of 8 bytes + 2 bytes from block 2 - * */ + */ memcpy(tagdata, pndef, 10 * BLOCK_SIZE + 2); /* Read the next one, up to the end of the data area */ @@ -232,14 +240,14 @@ static int read_dynamic_tag(uint8_t *cc, int length, void *data) return near_adapter_send(t1_tag->adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd), - segment_read_recv, t1_tag); + data_recv, t1_tag); } static int meta_recv(uint8_t *resp, int length, void *data) { struct t1_cookie *cookie = data; struct near_tag *tag; - struct type1_tag *t1_tag = NULL; + struct type1_tag *t1_tag; uint8_t *cc; int err = -EOPNOTSUPP; @@ -253,7 +261,7 @@ static int meta_recv(uint8_t *resp, int length, void *data) /* First byte is cmd status */ if (resp[OFFSET_STATUS_CMD] != 0) { - DBG("Command failed: 0x%x",resp[OFFSET_STATUS_CMD]); + DBG("Command failed: 0x%x", resp[OFFSET_STATUS_CMD]); err = -EIO; goto out_err; } @@ -297,7 +305,7 @@ static int meta_recv(uint8_t *resp, int length, void *data) t1_tag->tag = tag; memcpy(t1_tag->uid, cookie->uid, UID_LENGTH); - /*s Set the ReadWrite flag */ + /* Set the ReadWrite flag */ if (TAG_T1_WRITE_FLAG(cc) == TYPE1_NOWRITE_ACCESS) near_tag_set_ro(tag, TRUE); else @@ -331,18 +339,19 @@ static int meta_recv(uint8_t *resp, int length, void *data) near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_DYNAMIC); err = read_dynamic_tag(cc, length, t1_tag); } else { - err = -EOPNOTSUPP ; + err = -EOPNOTSUPP; } + if (err < 0) + g_free(t1_tag); + out_err: DBG("err %d", err); if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); - - return err; + return t1_cookie_release(err, cookie); } /* @@ -361,7 +370,7 @@ static int rid_resp(uint8_t *resp, int length, void *data) /* First byte is cmd status */ if (resp[OFFSET_STATUS_CMD] != 0) { - DBG("Command failed: 0x%x",resp[OFFSET_STATUS_CMD]); + DBG("Command failed: 0x%x", resp[OFFSET_STATUS_CMD]); err = -EIO; goto out_err; } @@ -390,7 +399,44 @@ out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); + return t1_cookie_release(err, cookie); +} + +static int nfctype1_read_meta(uint32_t adapter_idx, uint32_t target_idx, + near_tag_io_cb cb, uint8_t *uid) +{ + struct type1_cmd cmd; + struct t1_cookie *cookie; + int err; + + DBG(""); + + memset(&cmd, 0, sizeof(cmd)); + + cookie = g_try_malloc0(sizeof(struct t1_cookie)); + if (cookie == NULL) + return -ENOMEM; + + cookie->adapter_idx = adapter_idx; + cookie->target_idx = target_idx; + cookie->cb = cb; + + if (uid != NULL) { + cmd.cmd = CMD_READ_ALL; /* Read ALL cmd give 124 bytes */ + memcpy(cmd.uid, uid, UID_LENGTH); + memcpy(cookie->uid, uid, UID_LENGTH); + + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, + sizeof(cmd), meta_recv, cookie); + } else { + cmd.cmd = CMD_RID; + + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, + sizeof(cmd), rid_resp, cookie); + } + + if (err < 0) + t1_cookie_release(err, cookie); return err; } @@ -399,61 +445,29 @@ out_err: static int nfctype1_read(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb) { - struct type1_cmd t1_cmd; - struct t1_cookie *cookie; - uint8_t *uid, uid_length; + uint8_t *uid; + uint8_t uid_length; + int err; DBG(""); uid = near_tag_get_nfcid(adapter_idx, target_idx, &uid_length); if (uid == NULL || uid_length != UID_LENGTH) { - if (uid != NULL && uid_length != UID_LENGTH) { + if (uid != NULL) { near_error("Invalid UID"); g_free(uid); return -EINVAL; } - t1_cmd.cmd = CMD_RID; - t1_cmd.addr = 0; - t1_cmd.data[0] = 0; - memset(t1_cmd.uid, 0, UID_LENGTH); - - cookie = g_try_malloc0(sizeof(struct t1_cookie)); - if (cookie == NULL) { - g_free(uid); - return -ENOMEM; - } - - cookie->adapter_idx = adapter_idx; - cookie->target_idx = target_idx; - cookie->cb = cb; - - return near_adapter_send(adapter_idx, - (uint8_t *)&t1_cmd, sizeof(t1_cmd), - rid_resp, cookie); + return nfctype1_read_meta(adapter_idx, target_idx, cb, NULL); } - t1_cmd.cmd = CMD_READ_ALL; /* Read ALL cmd give 124 bytes */ - t1_cmd.addr = 0; /* NA */ - t1_cmd.data[0] = 0; - memcpy(t1_cmd.uid, uid, UID_LENGTH); - - cookie = g_try_malloc0(sizeof(struct t1_cookie)); - if (cookie == NULL) { - g_free(uid); - return -ENOMEM; - } - - cookie->adapter_idx = adapter_idx; - cookie->target_idx = target_idx; - memcpy(cookie->uid, uid, UID_LENGTH); - cookie->cb = cb; + err = nfctype1_read_meta(adapter_idx, target_idx, cb, uid); g_free(uid); - return near_adapter_send(adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd), - meta_recv, cookie); + return err; } static int write_nmn_e1_resp(uint8_t *resp, int length, void *data) @@ -473,9 +487,7 @@ static int write_nmn_e1_resp(uint8_t *resp, int length, void *data) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); - - return err; + return t1_cookie_release(err, cookie); } static int write_nmn_e1(struct t1_cookie *cookie) @@ -489,11 +501,11 @@ static int write_nmn_e1(struct t1_cookie *cookie) cmd.data[0] = TYPE1_MAGIC; memcpy(cmd.uid, cookie->uid, UID_LENGTH); - return near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), write_nmn_e1_resp, cookie); } -static int data_write(uint8_t *resp, int length, void *data) +static int data_write_resp(uint8_t *resp, int length, void *data) { struct t1_cookie *cookie = data; uint8_t addr = 0; @@ -504,12 +516,12 @@ static int data_write(uint8_t *resp, int length, void *data) if (length < 0) { err = length; - goto out; + goto out_err; } if (resp[OFFSET_STATUS_CMD] != 0) { err = -EIO; - goto out; + goto out_err; } if (cookie->ndef->offset > cookie->ndef->length) @@ -528,23 +540,21 @@ static int data_write(uint8_t *resp, int length, void *data) cookie->ndef->offset++; cookie->current_byte++; - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, - sizeof(cmd), data_write, cookie); + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, + sizeof(cmd), data_write_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); - - return err; + return t1_cookie_release(err, cookie); } -static int write_nmn_0(uint32_t adapter_idx, uint32_t target_idx, +static int data_write(uint32_t adapter_idx, uint32_t target_idx, struct near_ndef_message *ndef, near_tag_io_cb cb) { int err; @@ -582,17 +592,15 @@ static int write_nmn_0(uint32_t adapter_idx, uint32_t target_idx, g_free(uid); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, - sizeof(cmd), data_write, cookie); + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, + sizeof(cmd), data_write_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: - t1_cookie_release(cookie); - - return err; +out_err: + return t1_cookie_release(err, cookie); } /* @@ -621,16 +629,16 @@ static int nfctype1_write(uint32_t adapter_idx, uint32_t target_idx, return -EINVAL; /* This check is valid for only static tags. - * Max data length on Type 2 Tag including TLV's + * Max data length on Type 1 Tag including TLV's * is TYPE1_STATIC_MAX_DATA_SIZE */ if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) { if ((ndef->length + 3) > TYPE1_STATIC_MAX_DATA_SIZE) { - near_error("not enough space on data"); - return -ENOMEM; + near_error("not enough space on tag"); + return -ENOSPC; } } - return write_nmn_0(adapter_idx, target_idx, ndef, cb); + return data_write(adapter_idx, target_idx, ndef, cb); } static int check_presence(uint8_t *resp, int length, void *data) @@ -647,9 +655,7 @@ static int check_presence(uint8_t *resp, int length, void *data) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); - - return err; + return t1_cookie_release(err, cookie); } static int nfctype1_check_presence(uint32_t adapter_idx, @@ -683,17 +689,15 @@ static int nfctype1_check_presence(uint32_t adapter_idx, cookie->target_idx = target_idx; cookie->cb = cb; - err = near_adapter_send(adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd), - check_presence, cookie); + err = near_adapter_send(adapter_idx, (uint8_t *) &t1_cmd, + sizeof(t1_cmd), check_presence, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: - t1_cookie_release(cookie); - - return err; +out_err: + return t1_cookie_release(err, cookie); } static int format_resp(uint8_t *resp, int length, void *data) @@ -708,7 +712,7 @@ static int format_resp(uint8_t *resp, int length, void *data) if (length < 0 || resp[0] != 0) { err = -EIO; - goto out; + goto out_err; } if (cookie->current_byte < LEN_CC_BYTES) { @@ -719,30 +723,28 @@ static int format_resp(uint8_t *resp, int length, void *data) cookie->current_byte++; memcpy(cmd.uid, cookie->uid, UID_LENGTH); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), format_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; } else { tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -EINVAL; - goto out; + goto out_err; } DBG("Done formatting"); near_tag_set_blank(tag, FALSE); } -out: +out_err: if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t1_cookie_release(cookie); - - return err; + return t1_cookie_release(err, cookie); } static int nfctype1_format(uint32_t adapter_idx, uint32_t target_idx, @@ -773,7 +775,7 @@ static int nfctype1_format(uint32_t adapter_idx, uint32_t target_idx, cookie = g_try_malloc0(sizeof(struct t1_cookie)); if (cookie == NULL) { err = -EINVAL; - goto out; + goto out_err; } cookie->adapter_idx = adapter_idx; @@ -795,14 +797,14 @@ static int nfctype1_format(uint32_t adapter_idx, uint32_t target_idx, memcpy(cmd.uid, cookie->uid, UID_LENGTH); g_free(uid); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), format_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: g_free(cookie); g_free(uid); diff --git a/plugins/nfctype2.c b/plugins/nfctype2.c index 2858f24..62f6d0e 100644 --- a/plugins/nfctype2.c +++ b/plugins/nfctype2.c @@ -42,6 +42,13 @@ extern int mifare_read(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); +extern int mifare_check_presence(uint32_t adapter_idx, uint32_t target_idx, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); + +extern int mifare_write(uint32_t adapter_idx, uint32_t target_idx, + struct near_ndef_message *ndef, + near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype); + #define CMD_READ 0x30 #define CMD_READ_SIZE 0x02 @@ -97,10 +104,14 @@ struct type2_cc { uint8_t read_write; }; -static void t2_cookie_release(struct t2_cookie *cookie) +static int t2_cookie_release(int err, void *data) { + struct t2_cookie *cookie = data; + + DBG("%p", cookie); + if (cookie == NULL) - return; + return err; if (cookie->ndef) g_free(cookie->ndef->data); @@ -108,6 +119,8 @@ static void t2_cookie_release(struct t2_cookie *cookie) g_free(cookie->ndef); g_free(cookie); cookie = NULL; + + return err; } static int data_recv(uint8_t *resp, int length, void *data) @@ -162,7 +175,7 @@ static int data_recv(uint8_t *resp, int length, void *data) DBG("adapter %d", adapter_idx); return near_adapter_send(adapter_idx, - (uint8_t *)&cmd, CMD_READ_SIZE, + (uint8_t *) &cmd, CMD_READ_SIZE, data_recv, tag); } @@ -181,7 +194,7 @@ static int data_read(struct type2_tag *tag) adapter_idx = near_tag_get_adapter_idx(tag->tag); return near_adapter_send(adapter_idx, - (uint8_t *)&cmd, CMD_READ_SIZE, + (uint8_t *) &cmd, CMD_READ_SIZE, data_recv, tag); } @@ -197,12 +210,12 @@ static int meta_recv(uint8_t *resp, int length, void *data) if (length < 0) { err = length; - goto out; + goto out_err; } if (resp[0] != 0) { err = -EIO; - goto out; + goto out_err; } cc = TAG_DATA_CC(resp + NFC_HEADER_SIZE); @@ -213,18 +226,18 @@ static int meta_recv(uint8_t *resp, int length, void *data) TYPE2_DATA_SIZE_48 << 3)); if (err < 0) - goto out; + goto out_err; tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } t2_tag = g_try_malloc0(sizeof(struct type2_tag)); if (t2_tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } t2_tag->adapter_idx = cookie->adapter_idx; @@ -248,19 +261,18 @@ static int meta_recv(uint8_t *resp, int length, void *data) err = data_read(t2_tag); if (err < 0) - goto out; + goto out_tag; - t2_cookie_release(cookie); + return t2_cookie_release(err, cookie); - return 0; +out_tag: + g_free(t2_tag); -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t2_cookie_release(cookie); - - return err; + return t2_cookie_release(err, cookie); } static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx, @@ -283,7 +295,7 @@ static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx, cookie->target_idx = target_idx; cookie->cb = cb; - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, CMD_READ_SIZE, + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, CMD_READ_SIZE, meta_recv, cookie); if (err < 0) g_free(cookie); @@ -309,12 +321,12 @@ static int nfctype2_read(uint32_t adapter_idx, /* Specific Mifare read access */ case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K: case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K: - err= mifare_read( adapter_idx, target_idx, + err = mifare_read(adapter_idx, target_idx, cb, tgt_subtype); break; default: - DBG("Unknown TAG Type 2 subtype (%d)", tgt_subtype); + DBG("Unknown Tag Type 2 subtype %d", tgt_subtype); err = -1; break; } @@ -332,7 +344,7 @@ static int data_write_resp(uint8_t *resp, int length, void *data) if (length < 0 || resp[0] != 0) { err = -EIO; - goto out; + goto out_err; } if (cookie->ndef->offset > cookie->ndef->length) { @@ -341,9 +353,7 @@ static int data_write_resp(uint8_t *resp, int length, void *data) if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, 0); - t2_cookie_release(cookie); - - return 0; + return t2_cookie_release(0, cookie); } cmd.cmd = CMD_WRITE; @@ -361,22 +371,19 @@ static int data_write_resp(uint8_t *resp, int length, void *data) cookie->ndef->offset = cookie->ndef->length + 1; } - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), data_write_resp, cookie); - if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t2_cookie_release(cookie); - - return err; + return t2_cookie_release(err, cookie); } static int data_write(uint32_t adapter_idx, uint32_t target_idx, @@ -405,18 +412,16 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, cookie->ndef->offset += BLOCK_SIZE; cookie->current_block++; - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), data_write_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: - t2_cookie_release(cookie); - - return err; +out_err: + return t2_cookie_release(err, cookie); } static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx, @@ -425,6 +430,7 @@ static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx, { struct near_tag *tag; enum near_tag_sub_type tgt_subtype; + int err; DBG(""); @@ -437,21 +443,35 @@ static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx, tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx); - if (tgt_subtype != NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT) { - DBG("Unknown Tag Type 2 subtype (%d)", tgt_subtype); - return -1; - } - - /* This check is valid for only static tags. - * Max data length on Type 2 Tag including TLV's is NDEF_MAX_SIZE */ - if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) { - if ((ndef->length + 3) > NDEF_MAX_SIZE) { - near_error("not enough space on tag"); - return -ENOSPC; + switch (tgt_subtype) { + case NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT: + /* + * This check is valid for only static tags. + * Max data length on Type 2 Tag + * including TLV's is NDEF_MAX_SIZE + */ + if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) { + if ((ndef->length + 3) > NDEF_MAX_SIZE) { + near_error("not enough space on tag"); + return -ENOSPC; + } } + + err = data_write(adapter_idx, target_idx, ndef, cb); + break; + /* Specific Mifare write access */ + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K: + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K: + err = mifare_write(adapter_idx, target_idx, ndef, + cb, tgt_subtype); + break; + default: + DBG("Unknown TAG Type 2 subtype %d", tgt_subtype); + err = -EINVAL; + break; } - return data_write(adapter_idx, target_idx, ndef, cb); + return err; } static int check_presence(uint8_t *resp, int length, void *data) @@ -468,9 +488,7 @@ static int check_presence(uint8_t *resp, int length, void *data) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t2_cookie_release(cookie); - - return err; + return t2_cookie_release(err, cookie); } static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx, @@ -478,32 +496,49 @@ static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx, { struct type2_cmd cmd; struct t2_cookie *cookie; + enum near_tag_sub_type tgt_subtype; int err; DBG(""); - cmd.cmd = CMD_READ; - cmd.block = META_BLOCK_START; + tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx); - cookie = g_try_malloc0(sizeof(struct t2_cookie)); - if (cookie == NULL) - return -ENOMEM; + switch (tgt_subtype) { + case NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT: + cmd.cmd = CMD_READ; + cmd.block = META_BLOCK_START; - cookie->adapter_idx = adapter_idx; - cookie->target_idx = target_idx; - cookie->cb = cb; + cookie = g_try_malloc0(sizeof(struct t2_cookie)); + if (cookie == NULL) + return -ENOMEM; - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, CMD_READ_SIZE, - check_presence, cookie); - if (err < 0) - goto out; + cookie->adapter_idx = adapter_idx; + cookie->target_idx = target_idx; + cookie->cb = cb; - return 0; + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, + CMD_READ_SIZE, check_presence, cookie); + if (err < 0) + goto out_err; -out: - t2_cookie_release(cookie); + break; + /* Specific Mifare check presence */ + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K: + case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K: + err = mifare_check_presence(adapter_idx, target_idx, + cb, tgt_subtype); + break; + + default: + DBG("Unknown TAG Type 2 subtype %d", tgt_subtype); + err = -1; + break; + } return err; + +out_err: + return t2_cookie_release(err, cookie); } static int format_resp(uint8_t *resp, int length, void *data) @@ -516,25 +551,23 @@ static int format_resp(uint8_t *resp, int length, void *data) if (length < 0 || resp[0] != 0) { err = -EIO; - goto out; + goto out_err; } tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -EINVAL; - goto out; + goto out_err; } DBG("Done formatting"); near_tag_set_blank(tag, FALSE); -out: +out_err: if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t2_cookie_release(cookie); - - return err; + return t2_cookie_release(err, cookie); } static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx, @@ -558,7 +591,7 @@ static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx, tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx); if (tgt_subtype != NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT) { - DBG("Unknown Tag Type 2 subtype (%d)", tgt_subtype); + DBG("Unknown Tag Type 2 subtype %d", tgt_subtype); return -1; } @@ -568,7 +601,7 @@ static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx, if (t2_cc == NULL || cc_ndef == NULL || cookie == NULL) { err = -ENOMEM; - goto out; + goto out_err; } t2_cc->magic = TYPE2_MAGIC; @@ -580,17 +613,17 @@ static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx, cookie->target_idx = target_idx; cookie->current_block = CC_BLOCK_START; cookie->ndef = cc_ndef; - cookie->ndef->data = (uint8_t *)t2_cc; + cookie->ndef->data = (uint8_t *) t2_cc; cookie->cb = cb; cmd.cmd = CMD_WRITE; cmd.block = CC_BLOCK_START; - memcpy(cmd.data, (uint8_t *)t2_cc, BLOCK_SIZE); + memcpy(cmd.data, (uint8_t *) t2_cc, BLOCK_SIZE); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, sizeof(cmd), format_resp, cookie); -out: +out_err: if (err < 0) { g_free(t2_cc); g_free(cc_ndef); diff --git a/plugins/nfctype3.c b/plugins/nfctype3.c index b23c230..ffb401a 100644 --- a/plugins/nfctype3.c +++ b/plugins/nfctype3.c @@ -135,10 +135,14 @@ struct t3_cookie { uint8_t mc_block[BLOCK_SIZE]; }; -static void t3_cookie_release(struct t3_cookie *cookie) +static int t3_cookie_release(int err, void *data) { + struct t3_cookie *cookie = data; + + DBG("%p", cookie); + if (cookie == NULL) - return; + return err; if (cookie->ndef != NULL) g_free(cookie->ndef->data); @@ -146,6 +150,8 @@ static void t3_cookie_release(struct t3_cookie *cookie) g_free(cookie->ndef); g_free(cookie); cookie = NULL; + + return err; } /* common: Initialize structure to write block */ @@ -170,9 +176,9 @@ static void prepare_write_block(uint8_t *UID, struct type3_cmd *cmd, /* common: Initialize structure to read block */ static void prepare_read_block(uint8_t cur_block, uint8_t *UID, - struct type3_cmd *cmd ) + struct type3_cmd *cmd) { - cmd->cmd = CMD_READ_WO_ENCRYPT; /* command */ + cmd->cmd = CMD_READ_WO_ENCRYPT; /* command */ memcpy(cmd->data, UID, LEN_ID); /* IDm */ cmd->data[LEN_ID] = 1; /* number of service */ @@ -192,11 +198,11 @@ static int check_recv_frame(uint8_t *resp, uint8_t reply_code) int err = 0; if (resp[OFS_NFC_STATUS] != 0) { - DBG("NFC Command failed: 0x%x",resp[OFS_NFC_STATUS]); + DBG("NFC Command failed: 0x%x", resp[OFS_NFC_STATUS]); err = -EIO; } - if (resp[OFS_CMD_RESP] != reply_code ) { + if (resp[OFS_CMD_RESP] != reply_code) { DBG("Felica cmd failed: 0x%x", resp[OFS_CMD_RESP]); err = -EIO; } @@ -204,7 +210,7 @@ static int check_recv_frame(uint8_t *resp, uint8_t reply_code) return err; } -static int nfctype3_data_recv(uint8_t *resp, int length, void *data) +static int data_recv(uint8_t *resp, int length, void *data) { struct type3_tag *tag = data; struct type3_cmd cmd; @@ -222,11 +228,11 @@ static int nfctype3_data_recv(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } nfc_data = near_tag_get_data(tag->tag, &data_length); - length_read = length - OFS_READ_DATA ; + length_read = length - OFS_READ_DATA; current_length = tag->current_block * BLOCK_SIZE; if (current_length + (length - OFS_READ_DATA) > data_length) length_read = data_length - current_length; @@ -252,16 +258,17 @@ static int nfctype3_data_recv(uint8_t *resp, int length, void *data) tag->current_block += read_blocks; prepare_read_block(DATA_BLOCK_START + tag->current_block, - tag->IDm, &cmd ); + tag->IDm, &cmd); + + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len, + data_recv, tag); - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, cmd.len, - nfctype3_data_recv, tag); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && tag->cb) tag->cb(adapter_idx, target_idx, err); @@ -270,7 +277,7 @@ out: return err; } -static int nfctype3_data_read(struct type3_tag *tag) +static int data_read(struct type3_tag *tag) { struct type3_cmd cmd; uint32_t adapter_idx; @@ -286,7 +293,7 @@ static int nfctype3_data_read(struct type3_tag *tag) return near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len, - nfctype3_data_recv, tag); + data_recv, tag); } /* Read block 0 to retrieve the data length */ @@ -296,23 +303,23 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data) int err = 0; struct near_tag *tag; struct type3_tag *t3_tag = NULL; - uint32_t ndef_data_length; + uint32_t ndef_data_length; DBG("%d", length); if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_READ_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; if (resp[OFS_READ_FLAG] != 0) { DBG("Status 0x%x", resp[OFS_READ_FLAG]); err = -EIO; - goto out; + goto out_err; } /* Block 0:[11 - 13]: length is a 3 bytes value */ @@ -325,12 +332,12 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data) err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx, NULL, ndef_data_length); if (err < 0) - goto out; + goto out_err; tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } /* Block 0:[10]: RW Flag. 1 for RW */ @@ -342,10 +349,10 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data) t3_tag = g_try_malloc0(sizeof(struct type3_tag)); if (t3_tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } - memcpy(t3_tag->IDm, cookie->IDm , LEN_ID); + memcpy(t3_tag->IDm, cookie->IDm, LEN_ID); near_tag_set_idm(tag, cookie->IDm, LEN_ID); near_tag_set_attr_block(tag, resp + OFS_READ_DATA, BLOCK_SIZE); @@ -356,9 +363,9 @@ static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data) t3_tag->cb = cookie->cb; t3_tag->tag = tag; - err = nfctype3_data_read(t3_tag); + err = data_read(t3_tag); -out: +out_err: if (err < 0) { if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, @@ -367,9 +374,7 @@ out: g_free(t3_tag); } - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int poll_ndef_system_code(uint8_t *resp, int length, void *data) @@ -378,34 +383,32 @@ static int poll_ndef_system_code(uint8_t *resp, int length, void *data) int err = 0; struct type3_cmd cmd; - DBG(" length: %d", length); + DBG("length: %d", length); if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_POLL); if (err < 0) - goto out; + goto out_err; prepare_read_block(META_BLOCK_START, cookie->IDm, &cmd); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, nfctype3_recv_block_0, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data) @@ -419,12 +422,12 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_READ_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; if (resp[SYSTEM_OPTION_OFFSET] == 0x00) { DBG("Blank tag detected"); @@ -433,13 +436,13 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data) cookie->target_idx, NULL, 1 /* dummy length */); if (err < 0) - goto out; + goto out_err; tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } near_tag_set_idm(tag, cookie->IDm, LEN_ID); @@ -450,9 +453,7 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data) cookie->cb(cookie->adapter_idx, cookie->target_idx, 0); - t3_cookie_release(cookie); - - return 0; + return t3_cookie_release(0, cookie); } else { /* CMD POLL */ cmd.cmd = CMD_POLL; /* POLL command */ @@ -463,22 +464,20 @@ static int check_sys_op_in_mc_block(uint8_t *resp, int length, void *data) /* data len + 2 bytes */ cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ; - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len , poll_ndef_system_code, cookie); } if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int receive_system_code(uint8_t *resp, int length, void *data) @@ -488,26 +487,26 @@ static int receive_system_code(uint8_t *resp, int length, void *data) struct type3_cmd cmd; uint16_t system_code; - DBG(" length: %d", length); + DBG("length: %d", length); if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_POLL); if (err < 0) - goto out; + goto out_err; cookie->ic_type = resp[IC_TYPE_OFFSET]; memcpy(cookie->IDm, resp + OFS_IDM, LEN_ID); - system_code = ((uint16_t)(resp[length - 2])) << 8; + system_code = ((uint16_t) (resp[length - 2])) << 8; system_code |= resp[length - 1]; switch (resp[IC_TYPE_OFFSET]) { case FELICA_LITE_IC_TYPE: prepare_read_block(FELICA_LITE_MC_BLOCK, cookie->IDm, &cmd); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, check_sys_op_in_mc_block, cookie); break; @@ -523,22 +522,20 @@ static int receive_system_code(uint8_t *resp, int length, void *data) /* data len + 2 bytes */ cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ; - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, poll_ndef_system_code, cookie); } if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int nfctype3_read(uint32_t adapter_idx, @@ -558,7 +555,7 @@ static int nfctype3_read(uint32_t adapter_idx, cmd.data[3] = 0x00; /* time slot */ /* data len + 2 bytes */ - cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ; + cmd.len = LEN_CMD + LEN_CMD_LEN + 4; cookie = g_try_malloc0(sizeof(struct t3_cookie)); if (cookie == NULL) @@ -568,8 +565,8 @@ static int nfctype3_read(uint32_t adapter_idx, cookie->target_idx = target_idx; cookie->cb = cb; - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, - cmd.len , receive_system_code, cookie); + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, + cmd.len, receive_system_code, cookie); if (err < 0) g_free(cookie); @@ -585,22 +582,20 @@ static int update_attr_block_cb(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; DBG("Done writing"); -out: +out_err: if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int update_attr_block(struct t3_cookie *cookie) @@ -640,17 +635,17 @@ static int data_write_resp(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; if (cookie->ndef->offset >= cookie->ndef->length) { err = update_attr_block(cookie); if (err < 0) - goto out; + goto out_err; return 0; } @@ -669,20 +664,18 @@ static int data_write_resp(uint8_t *resp, int length, void *data) cookie->current_block++; cookie->ndef->offset += BLOCK_SIZE; - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, cmd.len, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, data_write_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int data_write(uint32_t adapter_idx, uint32_t target_idx, @@ -702,7 +695,7 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, cookie = g_try_malloc0(sizeof(struct t3_cookie)); if (cookie == NULL) { err = -ENOMEM; - goto out; + goto out_err; } cookie->adapter_idx = adapter_idx; @@ -714,7 +707,7 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, idm = near_tag_get_idm(tag, &len); if (idm == NULL) { err = -EINVAL; - goto out; + goto out_err; } memcpy(cookie->IDm, idm, len); @@ -722,16 +715,16 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, attr = near_tag_get_attr_block(tag, &len); if (attr == NULL) { err = -EINVAL; - goto out; + goto out_err; } memcpy(cookie->attr, attr, len); - nmaxb = (((uint16_t)(cookie->attr[3])) << 8) | cookie->attr[4]; + nmaxb = (((uint16_t) (cookie->attr[3])) << 8) | cookie->attr[4]; if (cookie->ndef->length > (nmaxb * BLOCK_SIZE)) { near_error("not enough space on tag"); err = -ENOSPC; - goto out; + goto out_err; } cookie->attr[9] = 0x0F; /* writing data in progress */ @@ -740,24 +733,22 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, for (i = 0; i < 14; i++) checksum += cookie->attr[i]; - cookie->attr[14] = (uint8_t)(checksum >> 8); - cookie->attr[15] = (uint8_t)(checksum); + cookie->attr[14] = (uint8_t) (checksum >> 8); + cookie->attr[15] = (uint8_t) checksum; prepare_write_block(cookie->IDm, &cmd, cookie->current_block, cookie->attr); cookie->current_block++; - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, cmd.len, + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, cmd.len, data_write_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: - t3_cookie_release(cookie); - - return err; +out_err: + return t3_cookie_release(err, cookie); } static int nfctype3_write(uint32_t adapter_idx, uint32_t target_idx, @@ -778,9 +769,9 @@ static int nfctype3_write(uint32_t adapter_idx, uint32_t target_idx, return data_write(adapter_idx, target_idx, ndef, tag, cb); } -static int nfctype3_check_recv_UID(uint8_t *resp, int length, void *data) +static int check_presence(uint8_t *resp, int length, void *data) { - struct t3_cookie *rcv_cookie = data; + struct t3_cookie *cookie = data; int err = 0; DBG("length %d", length); @@ -788,13 +779,11 @@ static int nfctype3_check_recv_UID(uint8_t *resp, int length, void *data) if (length < 0) err = -EIO; - if (rcv_cookie->cb) - rcv_cookie->cb(rcv_cookie->adapter_idx, - rcv_cookie->target_idx, err); - - t3_cookie_release(rcv_cookie); + if (cookie->cb) + cookie->cb(cookie->adapter_idx, + cookie->target_idx, err); - return err; + return t3_cookie_release(err, cookie); } static int nfctype3_check_presence(uint32_t adapter_idx, @@ -824,17 +813,16 @@ static int nfctype3_check_presence(uint32_t adapter_idx, cookie->target_idx = target_idx; cookie->cb = cb; - err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, - cmd.len , nfctype3_check_recv_UID, cookie); + err = near_adapter_send(adapter_idx, (uint8_t *) &cmd, + cmd.len, check_presence, cookie); + if (err < 0) - goto out; + goto out_err; return 0; -out: - t3_cookie_release(cookie); - - return err; +out_err: + return t3_cookie_release(err, cookie); } static int format_resp(uint8_t *resp, int length, void *data) @@ -847,17 +835,17 @@ static int format_resp(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx); if (tag == NULL) { err = -ENOMEM; - goto out; + goto out_err; } near_tag_set_ro(tag, FALSE); @@ -867,13 +855,11 @@ static int format_resp(uint8_t *resp, int length, void *data) DBG("Formatting is done"); -out: +out_err: if (cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int write_attr_block(uint8_t *resp, int length , void *data) @@ -887,12 +873,12 @@ static int write_attr_block(uint8_t *resp, int length , void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; cookie->attr[0] = NDEF_MAPPING_VERSION; cookie->attr[1] = MAX_READ_BLOCKS_PER_CHECK; @@ -918,20 +904,18 @@ static int write_attr_block(uint8_t *resp, int length , void *data) prepare_write_block(cookie->IDm, &cmd, META_BLOCK_START, cookie->attr); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, format_resp, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int write_mc_block(uint8_t *resp, int length, void *data) @@ -944,17 +928,17 @@ static int write_mc_block(uint8_t *resp, int length, void *data) if (length < 0) { err = -EIO; - goto out; + goto out_err; } err = check_recv_frame(resp, RESP_READ_WO_ENCRYPT); if (err < 0) - goto out; + goto out_err; if (resp[OFS_READ_FLAG] != 0) { DBG("Status 0x%x", resp[OFS_READ_FLAG]); err = -EIO; - goto out; + goto out_err; } memcpy(cookie->mc_block, resp + 14, BLOCK_SIZE); @@ -965,20 +949,18 @@ static int write_mc_block(uint8_t *resp, int length, void *data) cookie->mc_block[3] = 1; prepare_write_block(cookie->IDm, &cmd, FELICA_LITE_MC_BLOCK, cookie->mc_block); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, write_attr_block, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: +out_err: if (err < 0 && cookie->cb) cookie->cb(cookie->adapter_idx, cookie->target_idx, err); - t3_cookie_release(cookie); - - return err; + return t3_cookie_release(err, cookie); } static int nfctype3_format(uint32_t adapter_idx, @@ -1013,23 +995,21 @@ static int nfctype3_format(uint32_t adapter_idx, idm = near_tag_get_idm(tag, &len); if (idm == NULL) { err = -EINVAL; - goto out; + goto out_err; } memcpy(cookie->IDm, idm, len); prepare_read_block(FELICA_LITE_MC_BLOCK, cookie->IDm, &cmd); - err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, + err = near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len, write_mc_block, cookie); if (err < 0) - goto out; + goto out_err; return 0; -out: - t3_cookie_release(cookie); - - return err; +out_err: + return t3_cookie_release(err, cookie); } static struct near_tag_driver type1_driver = { diff --git a/plugins/nfctype4.c b/plugins/nfctype4.c index 76289a5..8a00e3d 100644 --- a/plugins/nfctype4.c +++ b/plugins/nfctype4.c @@ -40,7 +40,7 @@ #include #include -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define NFC_STATUS 0 #define NFC_STATUS_BYTE_LEN 1 @@ -207,7 +207,7 @@ static int ISO_send_cmd(uint8_t class, cmd->data[cmd_data_length] = 0; } - err = near_adapter_send(in_rcv->adapter_idx, (uint8_t *)cmd, + err = near_adapter_send(in_rcv->adapter_idx, (uint8_t *) cmd, total_cmd_length, cb, in_rcv); if (err < 0) g_free(in_rcv); @@ -248,8 +248,8 @@ static int ISO_ReadBinary(uint16_t offset, uint8_t readsize, return ISO_send_cmd( 0x00, /* CLA */ 0xB0, /* INS: Select file */ - (uint8_t)((offset & 0xFF00)>>8), - (uint8_t)(offset & 0xFF), + (uint8_t) ((offset & 0xFF00) >> 8), + (uint8_t) (offset & 0xFF), 0, /* no data send */ readsize, /* bytes to read */ FALSE, @@ -265,8 +265,8 @@ static int ISO_Update(uint16_t offset, uint8_t nlen, return ISO_send_cmd( 0x00, /* CLA */ 0xD6, /* INS: Select file */ - (uint8_t)((offset & 0xFF00) >> 8), - (uint8_t)(offset & 0xFF), + (uint8_t) ((offset & 0xFF00) >> 8), + (uint8_t) (offset & 0xFF), data, /* length of NDEF data */ nlen, /* NLEN + NDEF data */ FALSE, @@ -274,8 +274,12 @@ static int ISO_Update(uint16_t offset, uint8_t nlen, cookie); } -static int t4_cookie_release(int err, struct t4_cookie *cookie) +static int t4_cookie_release(int err, void *data) { + struct t4_cookie *cookie = data; + + DBG("%p", cookie); + if (cookie == NULL) return err; @@ -342,7 +346,7 @@ static int data_read_cb(uint8_t *resp, int length, void *data) cookie->r_apdu_max_size, data_read_cb, cookie); else err = ISO_ReadBinary(cookie->read_data + 2, - (uint8_t)remain_bytes, data_read_cb, cookie); + (uint8_t) remain_bytes, data_read_cb, cookie); if (err < 0) goto out_err; @@ -354,9 +358,9 @@ out_err: static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data) { - struct t4_cookie *cookie = data ; + struct t4_cookie *cookie = data; struct near_tag *tag; - int err = 0; + int err; DBG("%d", length); @@ -396,9 +400,10 @@ static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data) else near_tag_set_ro(tag, FALSE); - /* TODO: see how we can get the UID value: - * near_tag_set_uid(tag, resp + NFC_HEADER_SIZE, 8); - * */ + /* + * TODO: see how we can get the UID value: + * near_tag_set_uid(tag, resp + NFC_HEADER_SIZE, 8); + */ /* Read 1st block */ err = ISO_ReadBinary(2, cookie->r_apdu_max_size - 2, @@ -415,7 +420,7 @@ out_err: static int t4_select_NDEF_ID(uint8_t *resp, int length, void *data) { struct t4_cookie *cookie = data; - int err = 0; + int err; DBG("%d", length); @@ -445,9 +450,9 @@ out_err: static int t4_readbin_cc(uint8_t *resp, int length, void *data) { - struct t4_cookie *cookie = data ; - struct type4_cc *read_cc ; - int err = 0; + struct t4_cookie *cookie = data; + struct type4_cc *read_cc; + int err; DBG("%d", length); @@ -474,22 +479,22 @@ static int t4_readbin_cc(uint8_t *resp, int length, void *data) memcpy(read_cc, &resp[1], length - 2 - NFC_STATUS_BYTE_LEN) ; cookie->r_apdu_max_size = g_ntohs(read_cc->max_R_apdu_data_size) - - APDU_HEADER_LEN ; + APDU_HEADER_LEN; cookie->c_apdu_max_size = g_ntohs(read_cc->max_C_apdu_data_size); cookie->max_ndef_size = g_ntohs(read_cc->tlv_fc.max_ndef_size); - /* TODO 5.1.1 :TLV blocks can be zero, one or more... */ - /* TODO 5.1.2 :Must ignore proprietary blocks (x05)... */ - if (read_cc->tlv_fc.tag != 0x4) { - DBG("NDEF File Control tag not found !") ; - err = -EINVAL ; - goto out_err ; + /* TODO 5.1.1: TLV blocks can be zero, one or more... */ + /* TODO 5.1.2: Must ignore proprietary blocks (x05)... */ + if (read_cc->tlv_fc.tag != 0x4) { + DBG("NDEF File Control tag not found"); + err = -EINVAL; + goto out_err; } /* save rw conditions */ cookie->write_access = read_cc->tlv_fc.write_access; - err = ISO_Select((uint8_t *)&read_cc->tlv_fc.file_id, + err = ISO_Select((uint8_t *) &read_cc->tlv_fc.file_id, LEN_ISO_CC_FILEID, 0, t4_select_NDEF_ID, cookie); if (err < 0) goto out_err; @@ -503,7 +508,7 @@ out_err: static int t4_select_cc(uint8_t *resp, int length, void *data) { struct t4_cookie *cookie = data; - int err = 0; + int err; DBG("%d", length); @@ -550,7 +555,7 @@ out_err: static int t4_select_file_by_name_v1(uint8_t *resp, int length, void *data) { struct t4_cookie *cookie = data; - int err = 0 ; + int err; DBG("%d", length); @@ -586,7 +591,7 @@ out_err: static int t4_select_file_by_name_v2(uint8_t *resp, int length, void *data) { struct t4_cookie *cookie = data; - int err = 0 ; + int err; DBG("%d", length); @@ -633,7 +638,7 @@ static int nfctype4_read(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb) { struct t4_cookie *cookie; - int err = 0; + int err; DBG(""); @@ -647,7 +652,7 @@ static int nfctype4_read(uint32_t adapter_idx, cookie->target_idx = target_idx; cookie->cb = cb; cookie->tag = NULL; - cookie->read_data = 0;; + cookie->read_data = 0; /* Check for V2 type 4 tag */ err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2), @@ -720,7 +725,7 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, cookie = g_try_malloc0(sizeof(struct t4_cookie)); if (cookie == NULL) { err = -ENOMEM; - goto out; + goto out_err; } cookie->adapter_idx = adapter_idx; @@ -735,7 +740,7 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, if (cookie->max_ndef_size < cookie->ndef->length) { near_error("not enough space on tag to write data"); err = -ENOMEM; - goto out; + goto out_err; } if ((cookie->ndef->length - cookie->ndef->offset) > @@ -754,14 +759,12 @@ static int data_write(uint32_t adapter_idx, uint32_t target_idx, } if (err < 0) - goto out; + goto out_err; return 0; -out: - t4_cookie_release(err, cookie); - - return err; +out_err: + return t4_cookie_release(err, cookie); } static int nfctype4_write(uint32_t adapter_idx, uint32_t target_idx, @@ -802,7 +805,7 @@ static int nfctype4_check_presence(uint32_t adapter_idx, uint32_t target_idx, near_tag_io_cb cb) { struct t4_cookie *cookie; - int err = 0; + int err; DBG(""); @@ -816,7 +819,7 @@ static int nfctype4_check_presence(uint32_t adapter_idx, cookie->target_idx = target_idx; cookie->cb = cb; cookie->tag = NULL; - cookie->read_data = 0;; + cookie->read_data = 0; /* Check for V2 type 4 tag */ err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2), diff --git a/plugins/npp.c b/plugins/npp.c index 9f40291..33136ba 100644 --- a/plugins/npp.c +++ b/plugins/npp.c @@ -144,6 +144,7 @@ static near_bool_t npp_read(int client_fd, struct near_p2p_driver npp_driver = { .name = "NPP", .service_name = NEAR_DEVICE_SN_NPP, + .fallback_service_name = NULL, .read = npp_read, }; diff --git a/plugins/p2p.c b/plugins/p2p.c index f6352a1..845165f 100644 --- a/plugins/p2p.c +++ b/plugins/p2p.c @@ -106,7 +106,7 @@ static void free_client_data(gpointer data) DBG(""); - client_data = (struct p2p_data *)data; + client_data = (struct p2p_data *) data; if (client_data->driver->close != NULL) client_data->driver->close(client_data->fd, 0); @@ -165,7 +165,7 @@ static gboolean p2p_listener_event(GIOChannel *channel, GIOCondition condition, } client_addr_len = sizeof(client_addr); - client_fd = accept(server_fd, (struct sockaddr *)&client_addr, + client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len); if (client_fd < 0) { near_error("accept failed %d", client_fd); @@ -224,7 +224,7 @@ static int p2p_bind(struct near_p2p_driver *driver, uint32_t adapter_idx, addr.service_name_len = strlen(driver->service_name); strcpy(addr.service_name, driver->service_name); - err = bind(fd, (struct sockaddr *)&addr, + err = bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_nfc_llcp)); if (err < 0) { if (errno == EADDRINUSE) { @@ -264,6 +264,7 @@ static int p2p_bind(struct near_p2p_driver *driver, uint32_t adapter_idx, G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, p2p_listener_event, (gpointer) server_data); + g_io_channel_unref(channel); server_list = g_list_append(server_list, server_data); @@ -272,13 +273,14 @@ static int p2p_bind(struct near_p2p_driver *driver, uint32_t adapter_idx, static int p2p_listen(uint32_t adapter_idx, near_device_io_cb cb) { - int err = 0; + int err = -1; GSList *list; for (list = driver_list; list != NULL; list = list->next) { struct near_p2p_driver *driver = list->data; - err &= p2p_bind(driver, adapter_idx, cb); + if (p2p_bind(driver, adapter_idx, cb) == 0) + err = 0; } return err; @@ -305,7 +307,7 @@ static int p2p_connect(uint32_t adapter_idx, uint32_t target_idx, addr.service_name_len = strlen(driver->service_name); strcpy(addr.service_name, driver->service_name); - err = connect(fd, (struct sockaddr *)&addr, + err = connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_nfc_llcp)); if (err < 0) { near_error("Connect failed %d", err); @@ -331,12 +333,18 @@ static int p2p_push(uint32_t adapter_idx, uint32_t target_idx, if (strcmp(driver->service_name, service_name) != 0) continue; - + /* + * Because of Android's implementation, we have use SNEP for + * Handover. So, on Handover session, we try to connect to + * the handover service and fallback to SNEP on connect fail. + */ fd = p2p_connect(adapter_idx, target_idx, ndef, cb, driver); if (fd < 0) - return fd; - - return driver->push(fd, adapter_idx, target_idx, ndef, cb); + return p2p_push(adapter_idx, target_idx, ndef, + (char *) driver->fallback_service_name, cb); + else + return driver->push(fd, adapter_idx, target_idx, + ndef, cb); } return -1; diff --git a/plugins/p2p.h b/plugins/p2p.h index 5b74fb6..033ecd2 100644 --- a/plugins/p2p.h +++ b/plugins/p2p.h @@ -26,6 +26,7 @@ struct near_p2p_driver { const char *name; const char *service_name; + const char *fallback_service_name; near_bool_t (*read)(int client_fd, uint32_t adapter_idx, uint32_t target_idx, near_device_io_cb cb); diff --git a/plugins/snep.c b/plugins/snep.c index 488b765..9bde428 100644 --- a/plugins/snep.c +++ b/plugins/snep.c @@ -60,11 +60,13 @@ #define SNEP_RESP_REJECT 0xff #define SNEP_REQ_PUT_HEADER_LENGTH 6 +#define SNEP_REQ_GET_HEADER_LENGTH 10 /* TODO: Right now it is dummy, need to get correct value * from lower layers */ #define SNEP_REQ_MAX_FRAGMENT_LENGTH 128 struct p2p_snep_data { + uint8_t request_code; uint8_t *nfc_data; uint32_t nfc_data_length; uint32_t nfc_data_current_length; @@ -143,6 +145,87 @@ static void snep_close(int client_fd, int err) g_hash_table_remove(snep_client_hash, GINT_TO_POINTER(client_fd)); } +static void snep_response_with_info(int client_fd, uint8_t response, + uint8_t *data, int length) +{ + struct p2p_snep_resp_frame *resp; + + DBG("Response with info 0x%x (len:%d)", response, length); + + resp = g_try_malloc0(sizeof(struct p2p_snep_resp_frame) + length); + if (resp == NULL) { + DBG("Memory allocation error"); + return; + } + + /* Fill */ + resp->version = SNEP_VERSION; + resp->response = response; + resp->length = GUINT32_TO_BE(length); + memcpy(resp->info, data, length); + + send(client_fd, resp, sizeof(struct p2p_snep_resp_frame) + length, 0); + + g_free(resp); +} + +/* + * snep_parse_handover_record + * + * The hr frame should be here BUT: + * The first 4 bytes are the Max Allowed Length + * + * - Because of an Android's BUGs: + * - the Hr frame is not correct; a Hr record + * is embedded in a ... Hr record !!! The author + * used 'Hr' instead of 'cr' + * - The OOB block is badly written: + * - the payload ID should be the same in the 'ac' record + * and the OOB record. + * - The OOB data length bytes must be swapped (Big endian to Little E.) + * + * The hack fixes the first issue (bluetooth.c fixes the second) ! + * */ +static void snep_parse_handover_record(int client_fd, uint8_t *ndef, + uint32_t nfc_data_length) +{ + GList *records; + struct near_ndef_message *msg; + + if (ndef == NULL) + return; + + /* + * Bugfix Android: Fix 'cr' instead of 'Hr' + * Bug is in Google:HandoverManager.java:645 + */ + if (strncmp((char *)(ndef + 9), "Hr", 2) == 0) + *(ndef + 9) = 'c'; + + /* Parse the incoming frame */ + records = near_ndef_parse(ndef, nfc_data_length); + + /* + * If we received a Hr, we must build a Hs and send it. + * If the frame is a Hs, nothing more to do (SNEP REPLY is SUCCESS and + * the pairing is done in near_ndef_parse() + * */ + if (strncmp((char *)(ndef + 3), "Hr", 2) == 0) { + msg = near_ndef_prepare_handover_record("Hs", records->data, + NEAR_CARRIER_BLUETOOTH); + + near_info("Send SNEP / Hs frame"); + snep_response_with_info(client_fd, SNEP_RESP_SUCCESS, + msg->data, msg->length); + g_free(msg->data); + g_free(msg); + } + + near_ndef_records_free(records); + + return; +} + static near_bool_t snep_read_ndef(int client_fd, struct p2p_snep_data *snep_data) { @@ -184,20 +267,37 @@ static near_bool_t snep_read_ndef(int client_fd, return TRUE; } - snep_response_noinfo(client_fd, SNEP_RESP_SUCCESS); - if (near_device_add_data(snep_data->adapter_idx, snep_data->target_idx, - snep_data->nfc_data, - snep_data->nfc_data_length) < 0) - goto out; - - device = near_device_get_device(snep_data->adapter_idx, - snep_data->target_idx); - if (device == NULL) - goto out; - - records = near_ndef_parse(snep_data->nfc_data, + if (snep_data->request_code == SNEP_REQ_GET) { + /* + * This goes against the SNEP specification: + * "The default server SHALL NOT accept Get requests." but + * the first Android Handover implementation (Jelly Bean) + * does Handover through SNEP via GET frames...Since Android + * seems popular these days, we'd better support that spec + * violation. + * + * Parse the Hr and send a Hs + * Max allowed size in the first 4 bytes + */ + snep_parse_handover_record(client_fd, snep_data->nfc_data + 4, + snep_data->nfc_data_length - 4); + } else { + snep_response_noinfo(client_fd, SNEP_RESP_SUCCESS); + if (near_device_add_data(snep_data->adapter_idx, + snep_data->target_idx, + snep_data->nfc_data, + snep_data->nfc_data_length) < 0) + goto out; + + device = near_device_get_device(snep_data->adapter_idx, + snep_data->target_idx); + if (device == NULL) + goto out; + + records = near_ndef_parse(snep_data->nfc_data, snep_data->nfc_data_length); - near_device_add_records(device, records, snep_data->cb, 0); + near_device_add_records(device, records, snep_data->cb, 0); + } out: g_hash_table_remove(snep_client_hash, GINT_TO_POINTER(client_fd)); @@ -257,14 +357,16 @@ static near_bool_t snep_read(int client_fd, g_hash_table_insert(snep_client_hash, GINT_TO_POINTER(client_fd), snep_data); + snep_data->request_code = frame.request; + DBG("Request 0x%x", frame.request); switch (frame.request) { case SNEP_REQ_CONTINUE: - case SNEP_REQ_GET: near_error("Unsupported SNEP request code"); snep_response_noinfo(client_fd, SNEP_RESP_NOT_IMPL); return FALSE; + case SNEP_REQ_GET: case SNEP_REQ_PUT: return snep_read_ndef(client_fd, snep_data); } @@ -289,7 +391,7 @@ static void free_snep_push_data(gpointer userdata, int status) DBG(""); - data = (struct p2p_snep_put_req_data *)userdata; + data = (struct p2p_snep_put_req_data *) userdata; close(data->fd); @@ -328,6 +430,8 @@ static int snep_send_fragment(struct p2p_snep_put_req_data *req) static int snep_push_response(struct p2p_snep_put_req_data *req) { struct p2p_snep_resp_frame frame; + uint8_t *ndef; + uint32_t ndef_len; int bytes_recv, err; DBG(""); @@ -338,6 +442,9 @@ static int snep_push_response(struct p2p_snep_put_req_data *req) return bytes_recv; } + /* Check frame length */ + frame.length = g_ntohl(frame.length); + DBG("Response 0x%x", frame.response); switch (frame.response) { @@ -351,6 +458,30 @@ static int snep_push_response(struct p2p_snep_put_req_data *req) return frame.response; case SNEP_RESP_SUCCESS: + if (frame.length == 0) + return 0; + + /* Get the incoming data */ + ndef_len = frame.length; + ndef = g_try_malloc0(ndef_len); + if (ndef == NULL) + return -ENOMEM; + + bytes_recv = recv(req->fd, ndef, ndef_len, 0); + if (bytes_recv < 0) { + near_error("Could not read SNEP frame %d", bytes_recv); + return bytes_recv; + } + + /* Not enough bytes */ + if (bytes_recv < 6) + return -EINVAL; + + if (strncmp((char *)(ndef + 3), "Hs", 2) == 0) + snep_parse_handover_record(req->fd, ndef, ndef_len); + + g_free(ndef); + return 0; } @@ -430,6 +561,7 @@ static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx, GIOChannel *channel; gboolean fragmenting; int err; + int snep_req_header_length, snep_additional_length; DBG(""); @@ -453,8 +585,19 @@ static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx, max_fragment_len = SNEP_REQ_MAX_FRAGMENT_LENGTH; header.version = SNEP_VERSION; - header.request = SNEP_REQ_PUT; - header.length = GUINT32_TO_BE(ndef->length); + + /* Check if Hr or Hs for Handover over SNEP */ + if (*(char *)(ndef->data + 3) == 'H') { + header.request = SNEP_REQ_GET; /* Get for android */ + snep_req_header_length = SNEP_REQ_GET_HEADER_LENGTH; + snep_additional_length = 4; /* 4 Acceptable Length */ + } else { + header.request = SNEP_REQ_PUT; + snep_req_header_length = SNEP_REQ_PUT_HEADER_LENGTH; + snep_additional_length = 0; + } + + header.length = GUINT32_TO_BE(ndef->length + snep_additional_length); fragment = g_try_malloc0(sizeof(struct snep_fragment)); if (fragment == NULL) { @@ -462,8 +605,8 @@ static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx, goto error; } - if (max_fragment_len >= (ndef->length + SNEP_REQ_PUT_HEADER_LENGTH)) { - fragment->len = ndef->length + SNEP_REQ_PUT_HEADER_LENGTH; + if (max_fragment_len >= (ndef->length + snep_req_header_length)) { + fragment->len = ndef->length + snep_req_header_length; fragmenting = FALSE; } else { fragment->len = max_fragment_len; @@ -477,14 +620,18 @@ static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx, goto error; } - memcpy(fragment->data, (uint8_t *)&header, - SNEP_REQ_PUT_HEADER_LENGTH); + /* Header to data - common header */ + memcpy(fragment->data, (uint8_t *)&header, SNEP_REQ_PUT_HEADER_LENGTH); + + /* if GET, we add the Acceptable length */ + if (header.request == SNEP_REQ_GET) + *(uint32_t *)(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH) = + GUINT32_TO_BE(snep_req_header_length); if (fragmenting == TRUE) { - memcpy(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH, - ndef->data, - max_fragment_len - SNEP_REQ_PUT_HEADER_LENGTH); - ndef->offset = max_fragment_len - SNEP_REQ_PUT_HEADER_LENGTH; + memcpy(fragment->data + snep_req_header_length, ndef->data, + max_fragment_len - snep_req_header_length); + ndef->offset = max_fragment_len - snep_req_header_length; err = snep_push_prepare_fragments(req, ndef); if (err < 0) { @@ -494,7 +641,7 @@ static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx, } } else { - memcpy(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH, + memcpy(fragment->data + snep_req_header_length, ndef->data, ndef->length); } @@ -521,6 +668,7 @@ error: struct near_p2p_driver snep_driver = { .name = "SNEP", .service_name = NEAR_DEVICE_SN_SNEP, + .fallback_service_name = NEAR_DEVICE_SN_NPP, .read = snep_read, .push = snep_push, .close = snep_close, diff --git a/src/adapter.c b/src/adapter.c index 2ec0af6..e5f9e6a 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -368,8 +368,12 @@ static DBusMessage *set_property(DBusConnection *conn, err = __near_netlink_adapter_enable(adapter->idx, powered); if (err < 0) { - if (err == -EALREADY) - return __near_error_already_enabled(msg); + if (err == -EALREADY) { + if (powered == TRUE) + return __near_error_already_enabled(msg); + else + return __near_error_already_disabled(msg); + } return __near_error_failed(msg, -err); } @@ -420,6 +424,9 @@ static DBusMessage *stop_poll_loop(DBusConnection *conn, DBG("conn %p", conn); + if (adapter->polling == FALSE) + return __near_error_not_polling(msg); + err = __near_netlink_stop_poll(adapter->idx); if (err < 0) return __near_error_failed(msg, -err); @@ -577,6 +584,15 @@ int __near_adapter_set_dep_state(uint32_t idx, near_bool_t dep) if (dep == FALSE && adapter->constant_poll == TRUE) adapter_start_poll(adapter); + if (dep == FALSE) { + uint32_t target_idx; + + target_idx = __neard_device_get_idx(adapter->device_link); + __near_adapter_remove_target(idx, target_idx); + } else { + __near_adapter_devices_changed(idx); + } + return 0; } @@ -673,8 +689,6 @@ static void device_read_cb(uint32_t adapter_idx, uint32_t target_idx, return; } - - __near_adapter_devices_changed(adapter_idx); } static int adapter_add_tag(struct near_adapter *adapter, uint32_t target_idx, @@ -804,6 +818,8 @@ int __near_adapter_add_device(uint32_t idx, uint8_t *nfcid, uint8_t nfcid_len) adapter->dep_up = TRUE; polling_changed(adapter); + __near_adapter_devices_changed(idx); + return adapter_add_device(adapter, 0, nfcid, nfcid_len); } @@ -972,7 +988,7 @@ int near_adapter_disconnect(uint32_t idx) return -ENOLINK; tag_type = __near_tag_get_type(adapter->tag_link); - target_idx = __near_tag_get_idx(adapter->tag_link); + target_idx = near_tag_get_target_idx(adapter->tag_link); DBG("tag type %d", tag_type); @@ -1017,7 +1033,7 @@ int near_adapter_send(uint32_t idx, uint8_t *buf, size_t length, DBG("req %p cb %p data %p", req, cb, data); - req->target_idx = __near_tag_get_idx(adapter->tag_link); + req->target_idx = near_tag_get_target_idx(adapter->tag_link); req->cb = cb; req->data = data; diff --git a/src/bluetooth.c b/src/bluetooth.c index 1a4d4d1..60c65e3 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -63,6 +63,14 @@ #define COD_SIZE 3 #define OOB_SP_SIZE 16 +#define get_unaligned(ptr) \ +({ \ + struct __attribute__((packed)) { \ + typeof(*(ptr)) __v; \ + } *__p = (typeof(__p)) (ptr); \ + __p->__v; \ +}) + struct near_oob_data { char *def_adapter; @@ -620,8 +628,19 @@ int __near_bluetooth_parse_oob_record(uint8_t version, uint8_t *bt_data, oob = g_try_malloc0(sizeof(struct near_oob_data)); if (version == BT_MIME_V2_1) { - /* Total OOB data size (including size bytes)*/ - bt_oob_data_size = *((uint16_t *)(bt_data)); + /* + * Total OOB data size (including size bytes) + * Some implementations (e.g. Android 4.1) stores + * the data_size in big endian but NDEF forum spec (BT Secure + * Simple Pairing) requires a little endian. At the same time, + * the NDEF forum NDEF spec define a payload length as single + * byte (and the payload size IS the oob data size). + */ + bt_oob_data_size = + GUINT16_FROM_LE(get_unaligned((uint16_t *) bt_data)); + if (bt_oob_data_size > 0xFF) /* Big Endian */ + bt_oob_data_size = GUINT16_FROM_BE(bt_oob_data_size); + bt_oob_data_size -= 2 ; /* remove oob datas size len */ /* First item: BD_ADDR (mandatory) */ @@ -680,7 +699,7 @@ int __near_bluetooth_parse_oob_record(uint8_t version, uint8_t *bt_data, /* check and get the default adapter */ oob->def_adapter = g_strdup(bt_def_oob_data.def_adapter); - if (oob->bt_name == NULL) { + if (oob->def_adapter == NULL) { near_error("bt_get_default_adapter failed"); bt_eir_free(oob); return -EIO; diff --git a/src/device.c b/src/device.c index 4a201e8..de9cbe8 100644 --- a/src/device.c +++ b/src/device.c @@ -117,6 +117,11 @@ const char *__near_device_get_path(struct near_device *device) return device->path; } +uint32_t __neard_device_get_idx(struct near_device *device) +{ + return device->target_idx; +} + static void append_records(DBusMessageIter *iter, void *user_data) { struct near_device *device = user_data; diff --git a/src/error.c b/src/error.c index f166380..4012b5b 100644 --- a/src/error.c +++ b/src/error.c @@ -119,6 +119,12 @@ DBusMessage *__near_error_not_found(DBusMessage *msg) ".NotFound", "Not found"); } +DBusMessage *__near_error_not_polling(DBusMessage *msg) +{ + return g_dbus_create_error(msg, NFC_ERROR_INTERFACE + ".Failed", "Not polling"); +} + DBusMessage *__near_error_no_carrier(DBusMessage *msg) { return g_dbus_create_error(msg, NFC_ERROR_INTERFACE diff --git a/src/ndef.c b/src/ndef.c index e6c909d..2dd51e8 100644 --- a/src/ndef.c +++ b/src/ndef.c @@ -1552,9 +1552,9 @@ static struct near_ndef_ac_record *parse_ac_record(uint8_t *rec, /* Carrier data reference length */ ac_record->cdr_len = rec[offset]; + offset++; /* Carrier data reference */ - offset++; ac_record->cdr = rec[offset]; offset = offset + ac_record->cdr_len; diff --git a/src/near.h b/src/near.h index 1b9ccb1..aee34be 100644 --- a/src/near.h +++ b/src/near.h @@ -51,6 +51,7 @@ DBusMessage *__near_error_not_unique(DBusMessage *msg); DBusMessage *__near_error_not_supported(DBusMessage *msg); DBusMessage *__near_error_not_implemented(DBusMessage *msg); DBusMessage *__near_error_not_found(DBusMessage *msg); +DBusMessage *__near_error_not_polling(DBusMessage *msg); DBusMessage *__near_error_no_carrier(DBusMessage *msg); DBusMessage *__near_error_in_progress(DBusMessage *msg); DBusMessage *__near_error_already_exists(DBusMessage *msg); @@ -116,7 +117,6 @@ struct near_tag *__near_tag_add(uint32_t idx, uint32_t target_idx, uint8_t *nfcid, uint8_t nfcid_len); void __near_tag_remove(struct near_tag *tag); const char *__near_tag_get_path(struct near_tag *tag); -uint32_t __near_tag_get_idx(struct near_tag *tag); uint32_t __near_tag_get_type(struct near_tag *tag); void __near_tag_append_records(struct near_tag *tag, DBusMessageIter *iter); int __near_tag_read(struct near_tag *tag, near_tag_io_cb cb); @@ -130,6 +130,7 @@ int __near_tag_check_presence(struct near_tag *tag, near_tag_io_cb cb); int __near_device_init(void); void __near_device_cleanup(void); const char *__near_device_get_path(struct near_device *device); +uint32_t __neard_device_get_idx(struct near_device *device); struct near_device *__near_device_add(uint32_t idx, uint32_t target_idx, uint8_t *nfcid, uint8_t nfcid_len); void __near_device_remove(struct near_device *device); diff --git a/src/tag.c b/src/tag.c index 4450b92..b4aff76 100644 --- a/src/tag.c +++ b/src/tag.c @@ -624,12 +624,6 @@ const char *__near_tag_get_path(struct near_tag *tag) return tag->path; } - -uint32_t __near_tag_get_idx(struct near_tag *tag) -{ - return tag->target_idx; -} - uint32_t __near_tag_get_type(struct near_tag *tag) { return tag->type; diff --git a/test/bt-handover b/test/bt-handover new file mode 100755 index 0000000..95b6dbf --- /dev/null +++ b/test/bt-handover @@ -0,0 +1,69 @@ +#!/usr/bin/python + +import os +import sys +import gobject + +import dbus +import dbus.mainloop.glib + +from dbus.lowlevel import MethodCallMessage, HANDLER_RESULT_NOT_YET_HANDLED + +mainloop = gobject.MainLoop() + +def property_changed_adapter(name, value, path): + if name in ["Devices"]: + if (len(value) == 0): + print "Lost device, exiting" + mainloop.quit() + else: + device_path = value[0] + + print "Pairing with %s" % (device_path) + + device = dbus.Interface(bus.get_object("org.neard", device_path), "org.neard.Device") + device.Push(({ "Type" : "Handover", "Carrier" : "bluetooth"})) + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + bus = dbus.SystemBus() + + bluez_manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.bluez.Manager") + + bluez_adapter_path = bluez_manager.DefaultAdapter() + + bluez_adapter = dbus.Interface(bus.get_object("org.bluez", bluez_adapter_path), + "org.bluez.Adapter") + + for bluez_path in bluez_adapter.ListDevices(): + print("Removing %s" % (bluez_path)) + bluez_adapter.RemoveDevice(bluez_path) + + + manager = dbus.Interface(bus.get_object("org.neard", "/"), + "org.neard.Manager") + + properties = manager.GetProperties() + device_path = properties["Adapters"][0] + adapter = dbus.Interface(bus.get_object("org.neard", device_path), + "org.neard.Adapter") + + adapter_properties = adapter.GetProperties() + + for key in adapter_properties.keys(): + if key in ["Polling"]: + if adapter_properties[key] == dbus.Boolean(1): + print "Stoping poll on %s" % (device_path) + adapter.StopPollLoop() + + print "Starting poll on %s" % (device_path) + adapter.StartPollLoop("Initiator") + + bus.add_signal_receiver(property_changed_adapter, + bus_name="org.neard", + dbus_interface="org.neard.Adapter", + signal_name = "PropertyChanged", + path_keyword="path") + + mainloop.run() diff --git a/test/monitor-near b/test/monitor-near index 5758df0..fef307e 100755 --- a/test/monitor-near +++ b/test/monitor-near @@ -26,7 +26,7 @@ def property_changed_adapter(name, value, path): adapter = path[path.rfind("/") + 1:] if name in ["Polling"]: val = extract_bool(value) - elif name in ["Tags"]: + elif name in ["Tags", "Devices"]: val = extract_list(value) else: val = str(value) diff --git a/test/simple-agent b/test/simple-agent new file mode 100755 index 0000000..4db0a9f --- /dev/null +++ b/test/simple-agent @@ -0,0 +1,61 @@ +#!/usr/bin/python + +import gobject + +import dbus +import dbus.service +import dbus.mainloop.glib +import sys + +class NDEFAgent(dbus.service.Object): + + @dbus.service.method("org.neard.NDEFAgent", + in_signature='', out_signature='') + def Release(self): + print "Release" + mainloop.quit() + + @dbus.service.method("org.neard.NDEFAgent", + in_signature='a{sv}', + out_signature='') + def GetNDEF(self, fields): + print "GetNDEF" + + if fields.has_key("Records"): + for path in fields["Records"]: + print "Record path %s" % (path) + + return + + @dbus.service.method("org.neard.NDEFAgent", + in_signature='', out_signature='') + def Cancel(self): + print "Cancel" + +def print_usage(): + print "Usage:" + print "For NDEF agent:" + print "%s NDEF Type=" % (sys.argv[0]) + print "Help: %s help" % (sys.argv[0]) + sys.exit(1) + +if __name__ == '__main__': + if len(sys.argv) == 2 and sys.argv[1] == "help": + print_usage() + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + bus = dbus.SystemBus() + manager = dbus.Interface(bus.get_object('org.neard', "/"), + 'org.neard.Manager') + + if len(sys.argv) > 2: + if sys.argv[1] == "NDEF": + path = "/test/ndef/agent" + object = NDEFAgent(bus, path) + rec_type = sys.argv[2].replace("Type=", "", 1) + + manager.RegisterNDEFAgent(path, rec_type) + + mainloop = gobject.MainLoop() + mainloop.run()