diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-07-11 03:07:39 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-07-11 03:07:39 +0200 |
| commit | 7ddcacac7bbfaed303dcda7d14ab29cad94fd570 (patch) | |
| tree | 56d3ad19c6abd231853a93c872da3d3a44b19a8d /src/lib.rs | |
| parent | 069a57fcf85c725d000e03163716edb4ae3922ca (diff) | |
clm download, country config.
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 98 |
1 files changed, 79 insertions, 19 deletions
diff --git a/src/lib.rs b/src/lib.rs index 3609ecaeb..698c52f49 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
| @@ -1,9 +1,12 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait, concat_bytes, const_slice_from_raw_parts)] | 3 | #![feature(type_alias_impl_trait, concat_bytes, const_slice_from_raw_parts)] |
| 4 | #![deny(unused_must_use)] | ||
| 5 | |||
| 4 | // This mod MUST go first, so that the others see its macros. | 6 | // This mod MUST go first, so that the others see its macros. |
| 5 | pub(crate) mod fmt; | 7 | pub(crate) mod fmt; |
| 6 | 8 | ||
| 9 | mod countries; | ||
| 7 | mod structs; | 10 | mod structs; |
| 8 | 11 | ||
| 9 | use core::cell::Cell; | 12 | use core::cell::Cell; |
| @@ -206,14 +209,67 @@ pub struct Control<'a> { | |||
| 206 | 209 | ||
| 207 | impl<'a> Control<'a> { | 210 | impl<'a> Control<'a> { |
| 208 | pub async fn init(&mut self) { | 211 | pub async fn init(&mut self) { |
| 212 | const CHUNK_SIZE: usize = 1024; | ||
| 213 | |||
| 209 | let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) }; | 214 | let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) }; |
| 210 | 215 | ||
| 211 | let mut buf = [0; 8 + 12 + 1024]; | 216 | info!("Downloading CLM..."); |
| 212 | buf[0..8].copy_from_slice(b"clmload\x00"); | 217 | |
| 213 | buf[8..20].copy_from_slice(b"\x02\x10\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00"); | 218 | let mut offs = 0; |
| 214 | buf[20..].copy_from_slice(&clm[..1024]); | 219 | for chunk in clm.chunks(CHUNK_SIZE) { |
| 215 | self.ioctl(2, 263, 0, &buf).await; | 220 | let mut flag = DOWNLOAD_FLAG_HANDLER_VER; |
| 216 | info!("IOCTL done"); | 221 | if offs == 0 { |
| 222 | flag |= DOWNLOAD_FLAG_BEGIN; | ||
| 223 | } | ||
| 224 | offs += chunk.len(); | ||
| 225 | if offs == clm.len() { | ||
| 226 | flag |= DOWNLOAD_FLAG_END; | ||
| 227 | } | ||
| 228 | |||
| 229 | let header = DownloadHeader { | ||
| 230 | flag, | ||
| 231 | dload_type: DOWNLOAD_TYPE_CLM, | ||
| 232 | len: chunk.len() as _, | ||
| 233 | crc: 0, | ||
| 234 | }; | ||
| 235 | let mut buf = [0; 8 + 12 + CHUNK_SIZE]; | ||
| 236 | buf[0..8].copy_from_slice(b"clmload\x00"); | ||
| 237 | buf[8..20].copy_from_slice(&header.to_bytes()); | ||
| 238 | buf[20..][..chunk.len()].copy_from_slice(&chunk); | ||
| 239 | self.ioctl(2, 263, 0, &buf[..8 + 12 + chunk.len()]).await; | ||
| 240 | } | ||
| 241 | |||
| 242 | info!("Configuring misc stuff..."); | ||
| 243 | |||
| 244 | self.set_iovar_u32("bus:txglom", 0).await; | ||
| 245 | self.set_iovar_u32("apsta", 1).await; | ||
| 246 | self.set_iovar("cur_etheraddr", &[02, 03, 04, 05, 06, 07]).await; | ||
| 247 | |||
| 248 | let country = countries::WORLD_WIDE_XX; | ||
| 249 | let country_info = CountryInfo { | ||
| 250 | country_abbrev: [country.code[0], country.code[1], 0, 0], | ||
| 251 | country_code: [country.code[0], country.code[1], 0, 0], | ||
| 252 | rev: if country.rev == 0 { -1 } else { country.rev as _ }, | ||
| 253 | }; | ||
| 254 | self.set_iovar("country", &country_info.to_bytes()).await; | ||
| 255 | |||
| 256 | info!("INIT DONE"); | ||
| 257 | } | ||
| 258 | |||
| 259 | async fn set_iovar_u32(&mut self, name: &str, val: u32) { | ||
| 260 | self.set_iovar(name, &val.to_le_bytes()).await | ||
| 261 | } | ||
| 262 | |||
| 263 | async fn set_iovar(&mut self, name: &str, val: &[u8]) { | ||
| 264 | info!("set {} = {:02x}", name, val); | ||
| 265 | |||
| 266 | let mut buf = [0; 64]; | ||
| 267 | buf[..name.len()].copy_from_slice(name.as_bytes()); | ||
| 268 | buf[name.len()] = 0; | ||
| 269 | buf[name.len() + 1..][..val.len()].copy_from_slice(val); | ||
| 270 | |||
| 271 | let total_len = name.len() + 1 + val.len(); | ||
| 272 | self.ioctl(2, 263, 0, &buf[..total_len]).await; | ||
| 217 | } | 273 | } |
| 218 | 274 | ||
| 219 | async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &[u8]) { | 275 | async fn ioctl(&mut self, kind: u32, cmd: u32, iface: u32, buf: &[u8]) { |
| @@ -255,6 +311,7 @@ pub struct Runner<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> { | |||
| 255 | /// - strap to set to gSPI mode on boot. | 311 | /// - strap to set to gSPI mode on boot. |
| 256 | dio: Flex<'a, DIO>, | 312 | dio: Flex<'a, DIO>, |
| 257 | 313 | ||
| 314 | ioctl_seq: u8, | ||
| 258 | backplane_window: u32, | 315 | backplane_window: u32, |
| 259 | } | 316 | } |
| 260 | 317 | ||
| @@ -271,6 +328,8 @@ pub async fn new<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin>( | |||
| 271 | cs, | 328 | cs, |
| 272 | clk, | 329 | clk, |
| 273 | dio, | 330 | dio, |
| 331 | |||
| 332 | ioctl_seq: 0, | ||
| 274 | backplane_window: 0xAAAA_AAAA, | 333 | backplane_window: 0xAAAA_AAAA, |
| 275 | }; | 334 | }; |
| 276 | 335 | ||
| @@ -397,7 +456,6 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 397 | } | 456 | } |
| 398 | 457 | ||
| 399 | pub async fn run(mut self) -> ! { | 458 | pub async fn run(mut self) -> ! { |
| 400 | let mut old_irq = 0; | ||
| 401 | let mut buf = [0; 2048]; | 459 | let mut buf = [0; 2048]; |
| 402 | loop { | 460 | loop { |
| 403 | // Send stuff | 461 | // Send stuff |
| @@ -408,10 +466,6 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 408 | 466 | ||
| 409 | // Receive stuff | 467 | // Receive stuff |
| 410 | let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT); | 468 | let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT); |
| 411 | if irq != old_irq { | ||
| 412 | info!("irq: {:04x}", irq); | ||
| 413 | } | ||
| 414 | old_irq = irq; | ||
| 415 | 469 | ||
| 416 | if irq & IRQ_F2_PACKET_AVAILABLE != 0 { | 470 | if irq & IRQ_F2_PACKET_AVAILABLE != 0 { |
| 417 | let mut status = 0xFFFF_FFFF; | 471 | let mut status = 0xFFFF_FFFF; |
| @@ -421,7 +475,6 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 421 | 475 | ||
| 422 | if status & STATUS_F2_PKT_AVAILABLE != 0 { | 476 | if status & STATUS_F2_PKT_AVAILABLE != 0 { |
| 423 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; | 477 | let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; |
| 424 | info!("got len {}", len); | ||
| 425 | 478 | ||
| 426 | let cmd = cmd_word(false, true, FUNC_WLAN, 0, len); | 479 | let cmd = cmd_word(false, true, FUNC_WLAN, 0, len); |
| 427 | 480 | ||
| @@ -435,7 +488,7 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 435 | } | 488 | } |
| 436 | self.cs.set_high(); | 489 | self.cs.set_high(); |
| 437 | 490 | ||
| 438 | info!("rxd packet {:02x}", &buf[..len as usize]); | 491 | info!("rx {:02x}", &buf[..(len as usize).min(48)]); |
| 439 | 492 | ||
| 440 | self.rx(&buf[..len as usize]); | 493 | self.rx(&buf[..len as usize]); |
| 441 | } | 494 | } |
| @@ -466,15 +519,17 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 466 | 519 | ||
| 467 | let channel = sdpcm_header.channel_and_flags & 0x0f; | 520 | let channel = sdpcm_header.channel_and_flags & 0x0f; |
| 468 | 521 | ||
| 522 | let payload = &packet[sdpcm_header.header_length as _..]; | ||
| 523 | |||
| 469 | match channel { | 524 | match channel { |
| 470 | 0 => { | 525 | 0 => { |
| 471 | if packet.len() < SdpcmHeader::SIZE + CdcHeader::SIZE { | 526 | if payload.len() < CdcHeader::SIZE { |
| 472 | warn!("control packet too short, len={}", packet.len()); | 527 | warn!("payload too short, len={}", payload.len()); |
| 473 | return; | 528 | return; |
| 474 | } | 529 | } |
| 475 | 530 | ||
| 476 | let cdc_header = | 531 | let cdc_header = |
| 477 | CdcHeader::from_bytes(packet[SdpcmHeader::SIZE..][..CdcHeader::SIZE].try_into().unwrap()); | 532 | CdcHeader::from_bytes(payload[..CdcHeader::SIZE].try_into().unwrap()); |
| 478 | 533 | ||
| 479 | if cdc_header.id == self.state.ioctl_id.get() { | 534 | if cdc_header.id == self.state.ioctl_id.get() { |
| 480 | assert_eq!(cdc_header.status, 0); // todo propagate error | 535 | assert_eq!(cdc_header.status, 0); // todo propagate error |
| @@ -490,10 +545,13 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 490 | 545 | ||
| 491 | let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); | 546 | let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); |
| 492 | 547 | ||
| 548 | let seq = self.ioctl_seq; | ||
| 549 | self.ioctl_seq = self.ioctl_seq.wrapping_add(1); | ||
| 550 | |||
| 493 | let sdpcm_header = SdpcmHeader { | 551 | let sdpcm_header = SdpcmHeader { |
| 494 | len: total_len as u16, | 552 | len: total_len as u16, // TODO does this len need to be rounded up to u32? |
| 495 | len_inv: !total_len as u16, | 553 | len_inv: !total_len as u16, |
| 496 | sequence: 0x02, // todo | 554 | sequence: seq, |
| 497 | channel_and_flags: 0, // control channel | 555 | channel_and_flags: 0, // control channel |
| 498 | next_length: 0, | 556 | next_length: 0, |
| 499 | header_length: SdpcmHeader::SIZE as _, | 557 | header_length: SdpcmHeader::SIZE as _, |
| @@ -515,7 +573,9 @@ impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Runner<'a, PWR, CS, CLK, DIO> { | |||
| 515 | buf[SdpcmHeader::SIZE..][..CdcHeader::SIZE].copy_from_slice(&cdc_header.to_bytes()); | 573 | buf[SdpcmHeader::SIZE..][..CdcHeader::SIZE].copy_from_slice(&cdc_header.to_bytes()); |
| 516 | buf[SdpcmHeader::SIZE + CdcHeader::SIZE..][..data.len()].copy_from_slice(data); | 574 | buf[SdpcmHeader::SIZE + CdcHeader::SIZE..][..data.len()].copy_from_slice(data); |
| 517 | 575 | ||
| 518 | info!("txing {:02x}", &buf[..total_len]); | 576 | let total_len = (total_len + 3) & !3; // round up to 4byte |
| 577 | |||
| 578 | info!("tx {:02x}", &buf[..total_len.min(48)]); | ||
| 519 | 579 | ||
| 520 | let cmd = cmd_word(true, true, FUNC_WLAN, 0, total_len as _); | 580 | let cmd = cmd_word(true, true, FUNC_WLAN, 0, total_len as _); |
| 521 | self.cs.set_low(); | 581 | self.cs.set_low(); |
