Rework for custom pcb
This commit is contained in:
parent
5b985bd5ff
commit
2f8a9d7e5f
216
src/main.rs
216
src/main.rs
@ -1,46 +1,48 @@
|
|||||||
use image::imageops::FilterType;
|
use image::imageops::FilterType;
|
||||||
use image::{EncodableLayout, ImageError};
|
use image::{EncodableLayout, ImageError};
|
||||||
use nusb::transfer::{Bulk, Out, TransferError};
|
|
||||||
use nusb::MaybeFuture;
|
use nusb::MaybeFuture;
|
||||||
use nusb::{list_devices, ErrorKind};
|
use nusb::transfer::{Bulk, In, Out, TransferError};
|
||||||
|
use nusb::{ErrorKind, list_devices};
|
||||||
use reqwest::header::ACCEPT;
|
use reqwest::header::ACCEPT;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io::Write;
|
use std::io::{Read, Write};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Error {
|
struct Error {
|
||||||
message: &'static str
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nusb::Error> for Error {
|
impl From<nusb::Error> for Error {
|
||||||
fn from(value: nusb::Error) -> Self {
|
fn from(value: nusb::Error) -> Self {
|
||||||
Error{
|
Error {
|
||||||
message: match value.kind() {
|
message: match value.kind() {
|
||||||
ErrorKind::Disconnected => "Device disconnected",
|
ErrorKind::Disconnected => "Device disconnected".to_owned(),
|
||||||
ErrorKind::Busy => "Device busy",
|
ErrorKind::Busy => "Device busy".to_owned(),
|
||||||
ErrorKind::PermissionDenied => "No permission to access device",
|
ErrorKind::PermissionDenied => "No permission to access device".to_owned(),
|
||||||
ErrorKind::NotFound => "Device not found",
|
ErrorKind::NotFound => "Device not found".to_owned(),
|
||||||
ErrorKind::Unsupported => "Device not supported",
|
ErrorKind::Unsupported => "Device not supported".to_owned(),
|
||||||
_ => "Unknown error"
|
ErrorKind::Other => value.to_string(),
|
||||||
}
|
_ => "Unknown error".to_owned(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TransferError> for Error {
|
impl From<TransferError> for Error {
|
||||||
fn from(_: TransferError) -> Self {
|
fn from(value: TransferError) -> Self {
|
||||||
Error{
|
Error {
|
||||||
message: "Error during transfer"
|
message: value.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
impl From<std::io::Error> for Error {
|
||||||
fn from(_: std::io::Error) -> Self {
|
fn from(value: std::io::Error) -> Self {
|
||||||
Error {
|
Error {
|
||||||
message: "Error during transfer"
|
message: value.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +50,7 @@ impl From<std::io::Error> for Error {
|
|||||||
impl From<ImageError> for Error {
|
impl From<ImageError> for Error {
|
||||||
fn from(_: ImageError) -> Self {
|
fn from(_: ImageError) -> Self {
|
||||||
Error {
|
Error {
|
||||||
message: "Error reading image"
|
message: "Error reading image".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +58,7 @@ impl From<ImageError> for Error {
|
|||||||
impl From<reqwest::Error> for Error {
|
impl From<reqwest::Error> for Error {
|
||||||
fn from(_: reqwest::Error) -> Self {
|
fn from(_: reqwest::Error) -> Self {
|
||||||
Error {
|
Error {
|
||||||
message: "Error retrieving card info"
|
message: "Error retrieving card info".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +71,7 @@ impl Display for Error {
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ImageUris {
|
struct ImageUris {
|
||||||
pub png: String
|
pub png: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -77,17 +79,20 @@ struct ScryfallCardInfo {
|
|||||||
pub cmc: f32,
|
pub cmc: f32,
|
||||||
pub colors: Vec<String>,
|
pub colors: Vec<String>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub image_uris: ImageUris
|
pub image_uris: ImageUris,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RelevantCardInfo {
|
struct RelevantCardInfo {
|
||||||
pub cmc: u8,
|
pub cmc: u8,
|
||||||
pub colors: u8,
|
pub colors: u8,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub image: Vec<u8>
|
pub image: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<RelevantCardInfo, Error> {
|
fn get_relevant_card_info(
|
||||||
|
set_code: &str,
|
||||||
|
collector_number: &str,
|
||||||
|
) -> Result<RelevantCardInfo, Error> {
|
||||||
let client = reqwest::blocking::ClientBuilder::new()
|
let client = reqwest::blocking::ClientBuilder::new()
|
||||||
.user_agent("Digital MtG Token/0.1.0")
|
.user_agent("Digital MtG Token/0.1.0")
|
||||||
.build()?;
|
.build()?;
|
||||||
@ -95,23 +100,28 @@ fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<Rele
|
|||||||
let card_uri = format!("https://api.scryfall.com/cards/{set_code}/{collector_number}");
|
let card_uri = format!("https://api.scryfall.com/cards/{set_code}/{collector_number}");
|
||||||
let response = client.get(card_uri).header(ACCEPT, "*/*").send()?;
|
let response = client.get(card_uri).header(ACCEPT, "*/*").send()?;
|
||||||
let card_info: ScryfallCardInfo = response.json()?;
|
let card_info: ScryfallCardInfo = response.json()?;
|
||||||
let card_image = client.get(&card_info.image_uris.png).header(ACCEPT, "*/*").send()?.bytes()?.to_vec();
|
let card_image = client
|
||||||
|
.get(&card_info.image_uris.png)
|
||||||
|
.header(ACCEPT, "*/*")
|
||||||
|
.send()?
|
||||||
|
.bytes()?
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
let mut colors = 0;
|
let mut colors = 0;
|
||||||
for color in &card_info.colors {
|
for color in &card_info.colors {
|
||||||
match color.as_str() {
|
match color.as_str() {
|
||||||
"W" => {
|
"W" => {
|
||||||
colors |= 0b10000;
|
colors |= 0b10000;
|
||||||
},
|
}
|
||||||
"U" => {
|
"U" => {
|
||||||
colors |= 0b1000;
|
colors |= 0b1000;
|
||||||
},
|
}
|
||||||
"B" => {
|
"B" => {
|
||||||
colors |= 0b100;
|
colors |= 0b100;
|
||||||
},
|
}
|
||||||
"R" => {
|
"R" => {
|
||||||
colors |= 0b10;
|
colors |= 0b10;
|
||||||
},
|
}
|
||||||
"G" => {
|
"G" => {
|
||||||
colors |= 0b1;
|
colors |= 0b1;
|
||||||
}
|
}
|
||||||
@ -123,14 +133,17 @@ fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<Rele
|
|||||||
cmc: card_info.cmc.trunc() as u8,
|
cmc: card_info.cmc.trunc() as u8,
|
||||||
colors,
|
colors,
|
||||||
name: card_info.name.to_ascii_lowercase(),
|
name: card_info.name.to_ascii_lowercase(),
|
||||||
image: card_image
|
image: card_image,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let device = list_devices().wait()?
|
let device = list_devices()
|
||||||
|
.wait()?
|
||||||
.find(|dev| dev.vendor_id() == 0xCAFE && dev.product_id() == 0xCA6D)
|
.find(|dev| dev.vendor_id() == 0xCAFE && dev.product_id() == 0xCA6D)
|
||||||
.ok_or(Error { message: "Device not found" })?;
|
.ok_or(Error {
|
||||||
|
message: "Device not found".to_owned(),
|
||||||
|
})?;
|
||||||
|
|
||||||
let device = device.open().wait()?;
|
let device = device.open().wait()?;
|
||||||
let interface = device.claim_interface(1).wait()?;
|
let interface = device.claim_interface(1).wait()?;
|
||||||
@ -138,44 +151,107 @@ fn main() -> Result<(), Error> {
|
|||||||
let mut writer = interface.endpoint::<Bulk, Out>(0x01)?.writer(4096);
|
let mut writer = interface.endpoint::<Bulk, Out>(0x01)?.writer(4096);
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() == 1 {
|
if args.len() > 1 {
|
||||||
writer.write(&[0x42])?;
|
match args[1].as_str() {
|
||||||
writer.flush()?;
|
"erase" => {
|
||||||
|
writer.write_all(&[0x42])?;
|
||||||
|
writer.flush()?;
|
||||||
|
}
|
||||||
|
"test" => {
|
||||||
|
writer.write_all(&[0x69])?;
|
||||||
|
writer.flush()?;
|
||||||
|
|
||||||
|
let mut reader = interface
|
||||||
|
.endpoint::<Bulk, In>(0x81)?
|
||||||
|
.reader(128)
|
||||||
|
.with_read_timeout(Duration::from_millis(2500));
|
||||||
|
|
||||||
|
let mut temp = [0u8; 256];
|
||||||
|
let mut buf: Vec<u8> = vec![];
|
||||||
|
loop {
|
||||||
|
match reader.read(&mut temp) {
|
||||||
|
Ok(n) => {
|
||||||
|
if n > 0 {
|
||||||
|
buf.extend_from_slice(&temp[..n]);
|
||||||
|
println!("extended: {}", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => break,
|
||||||
|
r => {
|
||||||
|
r?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("buflen: {}", buf.len());
|
||||||
|
let mut card_index = 0;
|
||||||
|
for (i, val) in buf.iter().enumerate() {
|
||||||
|
print!("{:02x}", val);
|
||||||
|
if i > 0 && i % 256 == 0 {
|
||||||
|
println!();
|
||||||
|
let b0 = (buf[256 * card_index] as u16)
|
||||||
|
+ ((buf[256 * card_index + 1] as u16) << 8);
|
||||||
|
let is_used = b0 & 0x01 > 0;
|
||||||
|
let name_length = (b0 >> 1) & 0x1F;
|
||||||
|
let cmc = (b0 >> 6) & 0x1F;
|
||||||
|
let colors = (b0 >> 11) & 0x1F;
|
||||||
|
|
||||||
|
let name =
|
||||||
|
&buf[256 * card_index + 8..256 * card_index + 8 + name_length as usize];
|
||||||
|
|
||||||
|
for ch in name {
|
||||||
|
print!("{}", *ch as char);
|
||||||
|
}
|
||||||
|
println!(" ({})", name_length);
|
||||||
|
println!("Used: {}", is_used);
|
||||||
|
println!("CMC: {}", cmc);
|
||||||
|
println!("Colors: {}", colors);
|
||||||
|
println!();
|
||||||
|
|
||||||
|
card_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let slash_position = args[1].find("/").ok_or(Error {
|
||||||
|
message: "Error retrieving card info".to_owned(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let set_code = &args[1][0..slash_position];
|
||||||
|
let collectors_number = &args[1][slash_position + 1..];
|
||||||
|
|
||||||
|
let relevant_info = get_relevant_card_info(set_code, collectors_number)?;
|
||||||
|
|
||||||
|
// converted mana cost
|
||||||
|
writer.write_all(&[relevant_info.cmc])?;
|
||||||
|
|
||||||
|
// colors
|
||||||
|
writer.write_all(&[relevant_info.colors])?;
|
||||||
|
|
||||||
|
let name = relevant_info.name.as_str();
|
||||||
|
let name_len = if name.len() >= 32 { 31 } else { name.len() };
|
||||||
|
|
||||||
|
// length of card name
|
||||||
|
writer.write_all(&[name_len as u8])?;
|
||||||
|
|
||||||
|
// name of card
|
||||||
|
writer.write_all(&name.as_bytes()[0..name_len])?;
|
||||||
|
|
||||||
|
let img = image::load_from_memory(relevant_info.image.as_bytes())?;
|
||||||
|
let img = img.crop_imm(28, 28, img.width() - 56, img.height() - 56);
|
||||||
|
let img = img.resize_exact(240, 320, FilterType::Lanczos3);
|
||||||
|
let img = img.into_rgb8();
|
||||||
|
|
||||||
|
// image of card
|
||||||
|
writer.write_all(img.as_flat_samples().samples)?;
|
||||||
|
writer.flush()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error {
|
||||||
|
message: "Incorrect usage".to_owned(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
let slash_position = args[1].find("/").ok_or(Error {
|
|
||||||
message: "Error retrieving card info"
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let set_code = &args[1][0..slash_position];
|
|
||||||
let collectors_number = &args[1][slash_position + 1..];
|
|
||||||
|
|
||||||
let relevant_info = get_relevant_card_info(set_code, collectors_number)?;
|
|
||||||
|
|
||||||
// converted mana cost
|
|
||||||
writer.write(&[relevant_info.cmc])?;
|
|
||||||
|
|
||||||
// colors
|
|
||||||
writer.write(&[relevant_info.colors])?;
|
|
||||||
|
|
||||||
let name = relevant_info.name.as_str();
|
|
||||||
let name_len = if name.len() >= 32 { 31 } else { name.len() };
|
|
||||||
|
|
||||||
// length of card name
|
|
||||||
writer.write(&[name_len as u8])?;
|
|
||||||
|
|
||||||
// name of card
|
|
||||||
writer.write(name[0..name_len].as_bytes())?;
|
|
||||||
|
|
||||||
let img = image::load_from_memory(relevant_info.image.as_bytes())?;
|
|
||||||
let img = img.crop_imm(28, 28, img.width() - 56, img.height() - 56);
|
|
||||||
let img = img.resize_exact(240, 320, FilterType::Lanczos3);
|
|
||||||
let img = img.into_rgb8();
|
|
||||||
|
|
||||||
// image of card
|
|
||||||
writer.write_all(img.as_flat_samples().samples)?;
|
|
||||||
writer.flush()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user