1use core::mem::size_of;
53
54use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
55use kernel::hil::can;
56use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
57use kernel::syscall::{CommandReturn, SyscallDriver};
58use kernel::utilities::cells::{OptionalCell, TakeCell};
59use kernel::utilities::streaming_process_slice::StreamingProcessSlice;
60use kernel::ErrorCode;
61use kernel::ProcessId;
62
63use capsules_core::driver;
64pub const DRIVER_NUM: usize = driver::NUM::Can as usize;
65pub const BYTE4_MASK: usize = 0xff000000;
66pub const BYTE3_MASK: usize = 0xff0000;
67pub const BYTE2_MASK: usize = 0xff00;
68pub const BYTE1_MASK: usize = 0xff;
69
70mod error_upcalls {
71 pub const ERROR_TX: usize = 100;
72 pub const ERROR_RX: usize = 101;
73}
74
75mod up_calls {
76 pub const UPCALL_ENABLE: usize = 0;
77 pub const UPCALL_DISABLE: usize = 1;
78 pub const UPCALL_MESSAGE_SENT: usize = 2;
79 pub const UPCALL_MESSAGE_RECEIVED: usize = 3;
80 pub const UPCALL_RECEIVED_STOPPED: usize = 4;
81 pub const UPCALL_TRANSMISSION_ERROR: usize = 5;
82 pub const COUNT: u8 = 6;
83}
84
85mod ro_allow {
86 pub const RO_ALLOW_BUFFER: usize = 0;
87 pub const COUNT: u8 = 1;
88}
89
90mod rw_allow {
91 pub const RW_ALLOW_BUFFER: usize = 0;
92 pub const COUNT: u8 = 1;
93}
94
95pub struct CanCapsule<'a, Can: can::Can> {
96 can: &'a Can,
98
99 can_tx: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
101 can_rx: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
102
103 processes: Grant<
105 App,
106 UpcallCount<{ up_calls::COUNT }>,
107 AllowRoCount<{ ro_allow::COUNT }>,
108 AllowRwCount<{ rw_allow::COUNT }>,
109 >,
110 processid: OptionalCell<ProcessId>,
111
112 peripheral_state: OptionalCell<can::State>,
115}
116
117#[derive(Default)]
118pub struct App {
119 lost_messages: u32,
120}
121
122impl<'a, Can: can::Can> CanCapsule<'a, Can> {
123 pub fn new(
124 can: &'a Can,
125 grant: Grant<
126 App,
127 UpcallCount<{ up_calls::COUNT }>,
128 AllowRoCount<{ ro_allow::COUNT }>,
129 AllowRwCount<{ rw_allow::COUNT }>,
130 >,
131 can_tx: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
132 can_rx: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
133 ) -> CanCapsule<'a, Can> {
134 CanCapsule {
135 can,
136 can_tx: TakeCell::new(can_tx),
137 can_rx: TakeCell::new(can_rx),
138 processes: grant,
139 peripheral_state: OptionalCell::empty(),
140 processid: OptionalCell::empty(),
141 }
142 }
143
144 fn schedule_callback(&self, callback_number: usize, data: (usize, usize, usize)) {
145 self.processid.map(|processid| {
146 let _ = self.processes.enter(processid, |_app, kernel_data| {
147 let _ = kernel_data.schedule_upcall(callback_number, (data.0, data.1, data.2));
148 });
149 });
150 }
151
152 pub fn process_send_command(
155 &self,
156 processid: ProcessId,
157 id: can::Id,
158 length: usize,
159 ) -> Result<(), ErrorCode> {
160 self.processes
161 .enter(processid, |_, kernel_data| {
162 kernel_data
163 .get_readonly_processbuffer(ro_allow::RO_ALLOW_BUFFER)
164 .map_or_else(
165 |err| err.into(),
166 |buffer_ref| {
167 buffer_ref
168 .enter(|buffer| {
169 self.can_tx.take().map_or(
170 Err(ErrorCode::NOMEM),
171 |dest_buffer| {
172 for i in 0..length {
173 dest_buffer[i] = buffer[i].get();
174 }
175 match self.can.send(id, dest_buffer, length) {
176 Ok(()) => Ok(()),
177 Err((err, buf)) => {
178 self.can_tx.replace(buf);
179 Err(err)
180 }
181 }
182 },
183 )
184 })
185 .unwrap_or_else(|err| err.into())
186 },
187 )
188 })
189 .unwrap_or_else(|err| err.into())
190 }
191
192 pub fn is_valid_process(&self, processid: ProcessId) -> bool {
193 self.processid.map_or(true, |owning_process| {
194 self.processes
195 .enter(owning_process, |_, _| owning_process == processid)
196 .unwrap_or(true)
197 })
198 }
199}
200
201impl<Can: can::Can> SyscallDriver for CanCapsule<'_, Can> {
202 fn command(
203 &self,
204 command_num: usize,
205 arg1: usize,
206 arg2: usize,
207 processid: ProcessId,
208 ) -> CommandReturn {
209 if command_num == 0 {
211 return CommandReturn::success();
212 }
213
214 if !self.is_valid_process(processid) {
218 return CommandReturn::failure(ErrorCode::RESERVE);
219 } else {
220 self.processid.set(processid);
221 }
222
223 match command_num {
224 1 => match self.can.set_bitrate(arg1 as u32) {
226 Ok(()) => CommandReturn::success(),
227 Err(err) => CommandReturn::failure(err),
228 },
229
230 2 => {
232 match self.can.set_operation_mode(match arg1 {
233 0 => can::OperationMode::Loopback,
234 1 => can::OperationMode::Monitoring,
235 2 => can::OperationMode::Freeze,
236 _ => can::OperationMode::Normal,
237 }) {
238 Ok(()) => CommandReturn::success(),
239 Err(err) => CommandReturn::failure(err),
240 }
241 }
242
243 3 => match self.can.enable() {
245 Ok(()) => CommandReturn::success(),
246 Err(err) => CommandReturn::failure(err),
247 },
248
249 4 => match self.can.disable() {
251 Ok(()) => CommandReturn::success(),
252 Err(err) => CommandReturn::failure(err),
253 },
254
255 5 => {
257 let id = can::Id::Standard(arg1 as u16);
258 self.processid
259 .map_or(
260 CommandReturn::failure(ErrorCode::BUSY),
261 |processid| match self.process_send_command(processid, id, arg2) {
262 Ok(()) => CommandReturn::success(),
263 Err(err) => CommandReturn::failure(err),
264 },
265 )
266 }
267
268 6 => {
270 let id = can::Id::Extended(arg1 as u32);
271 self.processid
272 .map_or(
273 CommandReturn::failure(ErrorCode::BUSY),
274 |processid| match self.process_send_command(processid, id, arg2) {
275 Ok(()) => CommandReturn::success(),
276 Err(err) => CommandReturn::failure(err),
277 },
278 )
279 }
280
281 7 => {
283 self.can_rx
284 .take()
285 .map_or(CommandReturn::failure(ErrorCode::NOMEM), |dest_buffer| {
286 self.processes
287 .enter(processid, |_, kernel| {
288 match kernel.get_readwrite_processbuffer(0).map_or_else(
289 |err| err.into(),
290 |buffer_ref| {
291 buffer_ref
292 .enter(|buffer| {
293 if buffer.len()
296 >= 2 * can::STANDARD_CAN_PACKET_SIZE
297 + size_of::<u32>()
298 {
299 Ok(())
300 } else {
301 Err(ErrorCode::SIZE)
302 }
303 })
304 .unwrap_or_else(|err| err.into())
305 },
306 ) {
307 Ok(()) => match self.can.start_receive_process(dest_buffer) {
308 Ok(()) => CommandReturn::success(),
309 Err((err, _)) => CommandReturn::failure(err),
310 },
311 Err(err) => CommandReturn::failure(err),
312 }
313 })
314 .unwrap_or_else(|err| err.into())
315 })
316 }
317
318 8 => match self.can.stop_receive() {
320 Ok(()) => CommandReturn::success(),
321 Err(err) => CommandReturn::failure(err),
322 },
323
324 9 => {
326 match self.can.set_bit_timing(can::BitTiming {
327 segment1: ((arg1 & BYTE4_MASK) >> 24) as u8,
328 segment2: ((arg1 & BYTE3_MASK) >> 16) as u8,
329 propagation: arg2 as u8,
330 sync_jump_width: ((arg1 & BYTE2_MASK) >> 8) as u32,
331 baud_rate_prescaler: (arg1 & BYTE1_MASK) as u32,
332 }) {
333 Ok(()) => CommandReturn::success(),
334 Err(err) => CommandReturn::failure(err),
335 }
336 }
337
338 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
339 }
340 }
341
342 fn allocate_grant(&self, process_id: ProcessId) -> Result<(), kernel::process::Error> {
343 self.processes.enter(process_id, |_, _| {})
344 }
345}
346
347impl<Can: can::Can> can::ControllerClient for CanCapsule<'_, Can> {
348 fn state_changed(&self, state: can::State) {
351 self.peripheral_state.replace(state);
352 }
353
354 fn enabled(&self, status: Result<(), ErrorCode>) {
360 match status {
361 Ok(()) => match self.peripheral_state.take() {
362 Some(can::State::Running) => {
363 self.schedule_callback(up_calls::UPCALL_ENABLE, (0, 0, 0));
364 }
365 Some(can::State::Error(err)) => {
366 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
367 }
368 Some(can::State::Disabled) | None => {
369 self.schedule_callback(
370 up_calls::UPCALL_ENABLE,
371 (ErrorCode::OFF as usize, 0, 0),
372 );
373 }
374 },
375 Err(err) => {
376 self.peripheral_state.take();
377 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
378 }
379 }
380 }
381
382 fn disabled(&self, status: Result<(), ErrorCode>) {
388 match status {
389 Ok(()) => match self.peripheral_state.take() {
390 Some(can::State::Disabled) => {
391 self.schedule_callback(up_calls::UPCALL_DISABLE, (0, 0, 0));
392 }
393 Some(can::State::Error(err)) => {
394 self.schedule_callback(up_calls::UPCALL_DISABLE, (err as usize, 0, 0));
395 }
396 Some(can::State::Running) | None => {
397 self.schedule_callback(
398 up_calls::UPCALL_DISABLE,
399 (ErrorCode::FAIL as usize, 0, 0),
400 );
401 }
402 },
403 Err(err) => {
404 self.peripheral_state.take();
405 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
406 }
407 }
408 self.processid.clear();
409 }
410}
411
412impl<Can: can::Can> can::TransmitClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
413 fn transmit_complete(
416 &self,
417 status: Result<(), can::Error>,
418 buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
419 ) {
420 self.can_tx.replace(buffer);
421 match status {
422 Ok(()) => self.schedule_callback(up_calls::UPCALL_MESSAGE_SENT, (0, 0, 0)),
423 Err(err) => {
424 self.schedule_callback(
425 up_calls::UPCALL_TRANSMISSION_ERROR,
426 (error_upcalls::ERROR_TX, err as usize, 0),
427 );
428 }
429 }
430 }
431}
432
433impl<Can: can::Can> can::ReceiveClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
434 fn message_received(
437 &self,
438 id: can::Id,
439 buffer: &mut [u8; can::STANDARD_CAN_PACKET_SIZE],
440 _len: usize,
441 status: Result<(), can::Error>,
442 ) {
443 match status {
444 Ok(()) => {
445 let res: Result<(bool, u32), ErrorCode> =
446 self.processid.map_or(Err(ErrorCode::NOMEM), |processid| {
447 self.processes
448 .enter(processid, |app_data, kernel_data| {
449 kernel_data
450 .get_readwrite_processbuffer(rw_allow::RW_ALLOW_BUFFER)
451 .map_or_else(
452 |err| Err(err.into()),
453 |buffer_ref| {
454 buffer_ref
455 .mut_enter(|user_slice| {
456 StreamingProcessSlice::new(user_slice)
457 .append_chunk(buffer)
458 .inspect_err(|_err| {
459 app_data.lost_messages += 1;
460 })
461 })
462 .unwrap_or_else(|err| Err(err.into()))
463 },
464 )
465 })
466 .unwrap_or_else(|err| Err(err.into()))
467 });
468
469 match res {
470 Err(err) => self.schedule_callback(
471 up_calls::UPCALL_TRANSMISSION_ERROR,
472 (error_upcalls::ERROR_RX, err as usize, 0),
473 ),
474 Ok((_first_chunk, new_offset)) => self.schedule_callback(
475 up_calls::UPCALL_MESSAGE_RECEIVED,
476 (
477 0,
478 new_offset as usize,
479 match id {
480 can::Id::Standard(u16) => u16 as usize,
481 can::Id::Extended(u32) => u32 as usize,
482 },
483 ),
484 ),
485 }
486 }
487 Err(err) => {
488 let kernel_err: ErrorCode = err.into();
489 self.schedule_callback(
490 up_calls::UPCALL_TRANSMISSION_ERROR,
491 (error_upcalls::ERROR_RX, kernel_err.into(), 0),
492 )
493 }
494 }
495 }
496
497 fn stopped(&self, buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE]) {
498 self.can_rx.replace(buffer);
499 self.schedule_callback(up_calls::UPCALL_RECEIVED_STOPPED, (0, 0, 0));
500 }
501}