use errors::*;
use pcsc_sys::*;
use parameters::{Protocol, ShareMode, CardDisposition, InitializationType};
use logic::utils::parse_error_code;
use logic::{Context, Reader};
use std::ffi::CString;
use std::ptr;
use std::sync::Arc;
#[allow(dead_code)]
pub struct Card {
handle: SCARDHANDLE,
context: Arc<Context>, protocol: Protocol,
share: ShareMode,
to_disconnect: bool
}
impl Card {
pub fn connect_to(context: Arc<Context>, reader: &Reader, share_mode: ShareMode, preferred_protocol: Protocol) -> Result<Card> {
info!("Trying to connect to reader {}.", reader.get_name());
let mut card_handle: SCARDHANDLE = SCARDHANDLE::default(); let mut protocol_choice: DWORD = DWORD::default(); unsafe {
let reader_cstr = try!(CString::new(reader.get_name()) .chain_err(|| "failed to convert to CString")); try!(
parse_error_code(
SCardConnect(context.get_handle(), reader_cstr.as_ptr(), share_mode.to_value(), preferred_protocol.to_value(), &mut card_handle, &mut protocol_choice)));
}
let chosen_protocol = Protocol::from(protocol_choice);
info!("Connection to reader {} achieved.", reader.get_name());
Ok(Card { handle: card_handle, context: context, protocol: chosen_protocol, share: share_mode, to_disconnect: true})
}
pub fn get_pci(&self) -> Result<&SCARD_IO_REQUEST> {
let pci = unsafe { match self.protocol {
Protocol::T0 => &g_rgSCardT0Pci,
Protocol::T1 => &g_rgSCardT1Pci,
Protocol::Raw => &g_rgSCardRawPci,
_ => bail!("chosen protocol ({}) is not implemented")
}};
Ok(pci)
}
pub fn reconnect(&mut self, init_type: InitializationType) -> Result<()> {
let mut protocol_choice: DWORD = DWORD::default(); let result = unsafe {
parse_error_code(
SCardReconnect(self.handle, self.share.to_value(), self.protocol.to_value(), init_type.to_value(), &mut protocol_choice))
};
if result.is_err() {
self.to_disconnect = false;
return result;
}
else { self.to_disconnect = true;
}
let chosen_protocol = Protocol::from(protocol_choice);
self.protocol = chosen_protocol;
info!("Card reconnection achieved.");
Ok(())
}
pub fn send_raw_command(&self, cmd: &[u8], max_answer_size: usize) -> Result<Vec<u8>> {
debug!("Sending command {:?} expecting {} bytes in answer at most.", cmd, max_answer_size);
let mut rx_vec = vec![0;max_answer_size];
let mut rx_size = max_answer_size as u64;
unsafe {
let cmd_buf_ptr = cmd.as_ptr();
let rx_buf_ptr = rx_vec.as_mut_ptr();
try!(
parse_error_code(
SCardTransmit(self.handle, try!(self.get_pci()), cmd_buf_ptr, cmd.len() as u64, ptr::null_mut(), rx_buf_ptr, &mut rx_size)));
}
rx_vec.truncate(rx_size as usize);
Ok(rx_vec)
}
}
impl Drop for Card {
fn drop(&mut self) {
if self.to_disconnect {
unsafe { SCardDisconnect(self.handle, CardDisposition::Auto.to_value()); } }
}
}