+ pegoda_transceive(ph, PEGODA_CMD_PCD_CONFIG, NULL, 0, rbuf, &rlen);
+
+ return ph;
+out_free:
+ free(ph);
+ return NULL;
+}
+
+/* Transform crypto1 key from generic 6byte into rc632 specific 12byte */
+static int
+mifare_transform_key(const u_int8_t *key6, u_int8_t *key12)
+{
+ int i;
+ u_int8_t ln;
+ u_int8_t hn;
+
+ for (i = 0; i < 6; i++) {
+ ln = key6[i] & 0x0f;
+ hn = key6[i] >> 4;
+ key12[i * 2 + 1] = (~ln << 4) | ln;
+ key12[i * 2] = (~hn << 4) | hn;
+ }
+ return 0;
+}
+
+static int pegoda_auth_e2(struct pegoda_handle *ph,
+ u_int8_t keynr, u_int8_t sector)
+{
+ unsigned char buf[3];
+ unsigned char rbuf[16];
+ unsigned int rlen = sizeof(rbuf);
+
+ buf[0] = 0x60;
+ buf[1] = keynr; /* key number */
+ buf[2] = sector; /* sector */
+ rlen = sizeof(rbuf);
+ pegoda_transceive(ph, PEGODA_CMD_PICC_AUTH, buf, 3, rbuf, &rlen);
+
+ /* FIXME: check response */
+
+ return 0;
+}
+
+static int pegoda_auth_key(struct pegoda_handle *ph,
+ u_int8_t sector, const unsigned char *key6)
+{
+ unsigned char buf[1+4+12+1];
+ unsigned char rbuf[16];
+ unsigned int rlen = sizeof(rbuf);
+
+ buf[0] = 0x60;
+ memcpy(buf+1, ph->snr, 4);
+ mifare_transform_key(key6, buf+5);
+ buf[17] = sector;
+
+ pegoda_transceive(ph, PEGODA_CMD_PICC_AUTH_KEY, buf, 18, rbuf, &rlen);
+
+ /* FIXME: check response */
+
+ return 0;
+}
+
+static int pegoda_read16(struct pegoda_handle *ph,
+ u_int8_t page, unsigned char *rx)
+{
+ int rc;
+ unsigned int rlen = 16;
+
+ rc = pegoda_transceive(ph, PEGODA_CMD_PICC_READ,
+ &page, 1, rx, &rlen);
+ if (rlen != 16)
+ return -EIO;
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ unsigned char buf[256];
+ unsigned char rbuf[256];
+ unsigned int rlen = sizeof(rbuf);
+ struct pegoda_handle *ph;
+ int i;
+
+ ph = pegoda_open();
+ if (!ph)
+ exit(1);
+
+ /* LED off */
+ buf[0] = 0x00;
+ rlen = sizeof(rbuf);
+ pegoda_transceive(ph, PEGODA_CMD_SWITCH_LED, buf, 1, rbuf, &rlen);
+
+ /* anticollision */