static inline void kill_queue(struct isi_port *port, short queue) { struct isi_board *card = port->card; unsigned long base = card->base; u16 channel = port->channel; if (!lock_card(card)) return; outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw((queue << 8) | 0x06, base); InterruptTheCard(base); unlock_card(card); }
/* card->lock MUST NOT be held */ static inline void raise_dtr_rts(struct isi_port *port) { struct isi_board *card = port->card; unsigned long base = card->base; u16 channel = port->channel; if (!lock_card(card)) return; outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw(0x0f04, base); InterruptTheCard(base); port->status |= (ISI_DTR | ISI_RTS); unlock_card(card); }
static inline void drop_dtr(struct isi_port *port) { struct isi_board *card = port->card; unsigned long base = card->base; u16 channel = port->channel; if (!lock_card(card)) return; outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw(0x0404, base); InterruptTheCard(base); port->status &= ~ISI_DTR; unlock_card(card); }
static bool check_magic() { bool bFailure = false; int uid_data; for (uint32_t page = 0; page <= 1; page++) { // Show if the readout went well if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { ERR("tag was removed"); return false; } bFailure = false; } uid_data = 0x00000000; memcpy(mp.mpd.abtData, &uid_data, sizeof uid_data); memset(mp.mpd.abtData + 4, 0, 12); //Force the write without checking for errors - otherwise the writes to the sector 0 seem to complain nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp); } //Check that the ID is now set to 0x000000000000 if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { //printf("%u", mp.mpd.abtData); bool result = true; for (int i = 0; i <= 7; i++) { if (mp.mpd.abtData[i] != 0x00) result = false; } if (result) { return true; } } //Initially check if we can unlock via the MF method if (unlock_card()) { return true; } else { return false; } }
static void isicom_dtr_rts(struct tty_port *port, int on) { struct isi_port *ip = container_of(port, struct isi_port, port); struct isi_board *card = ip->card; unsigned long base = card->base; u16 channel = ip->channel; if (!lock_card(card)) return; if (on) { outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw(0x0f04, base); InterruptTheCard(base); ip->status |= (ISI_DTR | ISI_RTS); } else { outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw(0x0C04, base); InterruptTheCard(base); ip->status &= ~(ISI_DTR | ISI_RTS); } unlock_card(card); }
static void isicom_tx(unsigned long _data) { short count = (BOARD_COUNT-1), card, base; short txcount, wrd, residue, word_count, cnt; struct isi_port *port; struct tty_struct *tty; /* find next active board */ card = (prev_card + 1) & 0x0003; while(count-- > 0) { if (isi_card[card].status & BOARD_ACTIVE) break; card = (card + 1) & 0x0003; } if (!(isi_card[card].status & BOARD_ACTIVE)) goto sched_again; prev_card = card; count = isi_card[card].port_count; port = isi_card[card].ports; base = isi_card[card].base; for (;count > 0;count--, port++) { if (!lock_card_at_interrupt(&isi_card[card])) continue; /* port not active or tx disabled to force flow control */ if (!(port->flags & ASYNC_INITIALIZED) || !(port->status & ISI_TXOK)) unlock_card(&isi_card[card]); continue; tty = port->tty; if (tty == NULL) { unlock_card(&isi_card[card]); continue; } txcount = min_t(short, TX_SIZE, port->xmit_cnt); if (txcount <= 0 || tty->stopped || tty->hw_stopped) { unlock_card(&isi_card[card]); continue; } if (!(inw(base + 0x02) & (1 << port->channel))) { unlock_card(&isi_card[card]); continue; } pr_dbg("txing %d bytes, port%d.\n", txcount, port->channel + 1); outw((port->channel << isi_card[card].shift_count) | txcount, base); residue = NO; wrd = 0; while (1) { cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail)); if (residue == YES) { residue = NO; if (cnt > 0) { wrd |= (port->xmit_buf[port->xmit_tail] << 8); port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); port->xmit_cnt--; txcount--; cnt--; outw(wrd, base); } else { outw(wrd, base); break; } } if (cnt <= 0) break; word_count = cnt >> 1; outsw(base, port->xmit_buf+port->xmit_tail,word_count); port->xmit_tail = (port->xmit_tail + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1); txcount -= (word_count << 1); port->xmit_cnt -= (word_count << 1); if (cnt & 0x0001) { residue = YES; wrd = port->xmit_buf[port->xmit_tail]; port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); port->xmit_cnt--; txcount--; } } InterruptTheCard(base); if (port->xmit_cnt <= 0) port->status &= ~ISI_TXOK; if (port->xmit_cnt <= WAKEUP_CHARS) schedule_work(&port->bh_tqueue); unlock_card(&isi_card[card]); } /* schedule another tx for hopefully in about 10ms */ sched_again: if (!re_schedule) { re_schedule = 2; return; } init_timer(&tx); tx.expires = jiffies + HZ/100; tx.data = 0; tx.function = isicom_tx; add_timer(&tx); return; }
bool write_card(int write_block_zero) { uint32_t uiBlock; bool bFailure = false; uint32_t uiWriteBlocks = 0; if (write_block_zero) { if (!unlock_card()) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"Writing %d blocks |", uiBlocks + 1); #endif //! Write the card from begin to end; for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { //! Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { //! When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: tag was removed\n"); #endif sprintf(message_erreur,"Error: tag was removed !"); return false; } bFailure = false; } fflush(stdout); //! Try to authenticate for the current sector if (!write_block_zero && !authenticate(uiBlock)) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: authentication failed for block %02x\n", uiBlock); #endif sprintf(message_erreur,"Error: authentication failed for block %02x !", uiBlock); return false; } } if (is_trailer_block(uiBlock)) { //! Copy the keys over from our key dump and store the retrieved access bits memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6); memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4); memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6); //! Try to write the trailer if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { #ifdef DEBUG_PRINTF fprintf(stderr,"failed to write trailer block %d \n", uiBlock); #endif bFailure = true; } } else { //! The first block 0x00 is read only, skip this if (uiBlock == 0 && ! write_block_zero && ! magic2) continue; //! Make sure a earlier write did not fail if (!bFailure) { //! Try to write the data block memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); //! do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: incorrect BCC in MFD file!\n"); fprintf(stderr,"Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); #endif sprintf(message_erreur,"Error: incorrect BCC in MFD file! "); return false; } } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; } } } //! Show if the write went well for each block print_success_or_failure(bFailure, &uiWriteBlocks); if ((! bTolerateFailures) && bFailure) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); #endif fflush(stdout); return true; }
bool read_card(int read_unlocked) { int32_t iBlock; bool bFailure = false; uint32_t uiReadBlocks = 0; if (read_unlocked) { if (!unlock_card()) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"Reading out %d blocks |\n", uiBlocks + 1); #endif //! Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { //! Authenticate everytime we reach a trailer block if (is_trailer_block(iBlock)) { if (bFailure) { //! When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: tag was removed\n"); #endif sprintf(message_erreur,"Error: tag was removed !"); return false; } bFailure = false; } fflush(stdout); //! Try to authenticate for the current sector if (!read_unlocked && !authenticate(iBlock)) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: authentication failed for block 0x%02x\n", iBlock); #endif sprintf(message_erreur,"Error: authentication failed for block 0x%02x !", iBlock); return false; } //! Try to read out the trailer if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if (read_unlocked) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); } else { //! Copy the keys over from our key dump and store the retrieved access bits memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6); memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4); memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6); } } else { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nfailed to read trailer block 0x%02x\n", iBlock); #endif bFailure = true; } } else { //! Make sure a earlier readout did not fail if (!bFailure) { //! Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); } else { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: unable to read block 0x%02x\n", iBlock); #endif bFailure = true; } } } //! Show if the readout went well for each block print_success_or_failure(bFailure, &uiReadBlocks); if ((! bTolerateFailures) && bFailure) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done : %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); #endif fflush(stdout); return true; }