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 kernel_data
148 .schedule_upcall(callback_number, (data.0, data.1, data.2))
149 .ok();
150 });
151 });
152 }
153
154 pub fn process_send_command(
157 &self,
158 processid: ProcessId,
159 id: can::Id,
160 length: usize,
161 ) -> Result<(), ErrorCode> {
162 self.processes
163 .enter(processid, |_, kernel_data| {
164 kernel_data
165 .get_readonly_processbuffer(ro_allow::RO_ALLOW_BUFFER)
166 .map_or_else(
167 |err| err.into(),
168 |buffer_ref| {
169 buffer_ref
170 .enter(|buffer| {
171 self.can_tx.take().map_or(
172 Err(ErrorCode::NOMEM),
173 |dest_buffer| {
174 for i in 0..length {
175 dest_buffer[i] = buffer[i].get();
176 }
177 match self.can.send(id, dest_buffer, length) {
178 Ok(()) => Ok(()),
179 Err((err, buf)) => {
180 self.can_tx.replace(buf);
181 Err(err)
182 }
183 }
184 },
185 )
186 })
187 .unwrap_or_else(|err| err.into())
188 },
189 )
190 })
191 .unwrap_or_else(|err| err.into())
192 }
193
194 pub fn is_valid_process(&self, processid: ProcessId) -> bool {
195 self.processid.map_or(true, |owning_process| {
196 self.processes
197 .enter(owning_process, |_, _| owning_process == processid)
198 .unwrap_or(true)
199 })
200 }
201}
202
203impl<Can: can::Can> SyscallDriver for CanCapsule<'_, Can> {
204 fn command(
205 &self,
206 command_num: usize,
207 arg1: usize,
208 arg2: usize,
209 processid: ProcessId,
210 ) -> CommandReturn {
211 if command_num == 0 {
213 return CommandReturn::success();
214 }
215
216 if !self.is_valid_process(processid) {
220 return CommandReturn::failure(ErrorCode::RESERVE);
221 } else {
222 self.processid.set(processid);
223 }
224
225 match command_num {
226 1 => match self.can.set_bitrate(arg1 as u32) {
228 Ok(()) => CommandReturn::success(),
229 Err(err) => CommandReturn::failure(err),
230 },
231
232 2 => {
234 match self.can.set_operation_mode(match arg1 {
235 0 => can::OperationMode::Loopback,
236 1 => can::OperationMode::Monitoring,
237 2 => can::OperationMode::Freeze,
238 _ => can::OperationMode::Normal,
239 }) {
240 Ok(()) => CommandReturn::success(),
241 Err(err) => CommandReturn::failure(err),
242 }
243 }
244
245 3 => match self.can.enable() {
247 Ok(()) => CommandReturn::success(),
248 Err(err) => CommandReturn::failure(err),
249 },
250
251 4 => match self.can.disable() {
253 Ok(()) => CommandReturn::success(),
254 Err(err) => CommandReturn::failure(err),
255 },
256
257 5 => {
259 let id = can::Id::Standard(arg1 as u16);
260 self.processid
261 .map_or(
262 CommandReturn::failure(ErrorCode::BUSY),
263 |processid| match self.process_send_command(processid, id, arg2) {
264 Ok(()) => CommandReturn::success(),
265 Err(err) => CommandReturn::failure(err),
266 },
267 )
268 }
269
270 6 => {
272 let id = can::Id::Extended(arg1 as u32);
273 self.processid
274 .map_or(
275 CommandReturn::failure(ErrorCode::BUSY),
276 |processid| match self.process_send_command(processid, id, arg2) {
277 Ok(()) => CommandReturn::success(),
278 Err(err) => CommandReturn::failure(err),
279 },
280 )
281 }
282
283 7 => {
285 self.can_rx
286 .take()
287 .map_or(CommandReturn::failure(ErrorCode::NOMEM), |dest_buffer| {
288 self.processes
289 .enter(processid, |_, kernel| {
290 match kernel.get_readwrite_processbuffer(0).map_or_else(
291 |err| err.into(),
292 |buffer_ref| {
293 buffer_ref
294 .enter(|buffer| {
295 if buffer.len()
298 >= 2 * can::STANDARD_CAN_PACKET_SIZE
299 + size_of::<u32>()
300 {
301 Ok(())
302 } else {
303 Err(ErrorCode::SIZE)
304 }
305 })
306 .unwrap_or_else(|err| err.into())
307 },
308 ) {
309 Ok(()) => match self.can.start_receive_process(dest_buffer) {
310 Ok(()) => CommandReturn::success(),
311 Err((err, _)) => CommandReturn::failure(err),
312 },
313 Err(err) => CommandReturn::failure(err),
314 }
315 })
316 .unwrap_or_else(|err| err.into())
317 })
318 }
319
320 8 => match self.can.stop_receive() {
322 Ok(()) => CommandReturn::success(),
323 Err(err) => CommandReturn::failure(err),
324 },
325
326 9 => {
328 match self.can.set_bit_timing(can::BitTiming {
329 segment1: ((arg1 & BYTE4_MASK) >> 24) as u8,
330 segment2: ((arg1 & BYTE3_MASK) >> 16) as u8,
331 propagation: arg2 as u8,
332 sync_jump_width: ((arg1 & BYTE2_MASK) >> 8) as u32,
333 baud_rate_prescaler: (arg1 & BYTE1_MASK) as u32,
334 }) {
335 Ok(()) => CommandReturn::success(),
336 Err(err) => CommandReturn::failure(err),
337 }
338 }
339
340 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
341 }
342 }
343
344 fn allocate_grant(&self, process_id: ProcessId) -> Result<(), kernel::process::Error> {
345 self.processes.enter(process_id, |_, _| {})
346 }
347}
348
349impl<Can: can::Can> can::ControllerClient for CanCapsule<'_, Can> {
350 fn state_changed(&self, state: can::State) {
353 self.peripheral_state.replace(state);
354 }
355
356 fn enabled(&self, status: Result<(), ErrorCode>) {
362 match status {
363 Ok(()) => match self.peripheral_state.take() {
364 Some(can::State::Running) => {
365 self.schedule_callback(up_calls::UPCALL_ENABLE, (0, 0, 0));
366 }
367 Some(can::State::Error(err)) => {
368 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
369 }
370 Some(can::State::Disabled) | None => {
371 self.schedule_callback(
372 up_calls::UPCALL_ENABLE,
373 (ErrorCode::OFF as usize, 0, 0),
374 );
375 }
376 },
377 Err(err) => {
378 self.peripheral_state.take();
379 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
380 }
381 }
382 }
383
384 fn disabled(&self, status: Result<(), ErrorCode>) {
390 match status {
391 Ok(()) => match self.peripheral_state.take() {
392 Some(can::State::Disabled) => {
393 self.schedule_callback(up_calls::UPCALL_DISABLE, (0, 0, 0));
394 }
395 Some(can::State::Error(err)) => {
396 self.schedule_callback(up_calls::UPCALL_DISABLE, (err as usize, 0, 0));
397 }
398 Some(can::State::Running) | None => {
399 self.schedule_callback(
400 up_calls::UPCALL_DISABLE,
401 (ErrorCode::FAIL as usize, 0, 0),
402 );
403 }
404 },
405 Err(err) => {
406 self.peripheral_state.take();
407 self.schedule_callback(up_calls::UPCALL_ENABLE, (err as usize, 0, 0));
408 }
409 }
410 self.processid.clear();
411 }
412}
413
414impl<Can: can::Can> can::TransmitClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
415 fn transmit_complete(
418 &self,
419 status: Result<(), can::Error>,
420 buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
421 ) {
422 self.can_tx.replace(buffer);
423 match status {
424 Ok(()) => self.schedule_callback(up_calls::UPCALL_MESSAGE_SENT, (0, 0, 0)),
425 Err(err) => {
426 self.schedule_callback(
427 up_calls::UPCALL_TRANSMISSION_ERROR,
428 (error_upcalls::ERROR_TX, err as usize, 0),
429 );
430 }
431 }
432 }
433}
434
435impl<Can: can::Can> can::ReceiveClient<{ can::STANDARD_CAN_PACKET_SIZE }> for CanCapsule<'_, Can> {
436 fn message_received(
439 &self,
440 id: can::Id,
441 buffer: &mut [u8; can::STANDARD_CAN_PACKET_SIZE],
442 _len: usize,
443 status: Result<(), can::Error>,
444 ) {
445 match status {
446 Ok(()) => {
447 let res: Result<(bool, u32), ErrorCode> =
448 self.processid.map_or(Err(ErrorCode::NOMEM), |processid| {
449 self.processes
450 .enter(processid, |app_data, kernel_data| {
451 kernel_data
452 .get_readwrite_processbuffer(rw_allow::RW_ALLOW_BUFFER)
453 .map_or_else(
454 |err| Err(err.into()),
455 |buffer_ref| {
456 buffer_ref
457 .mut_enter(|user_slice| {
458 StreamingProcessSlice::new(user_slice)
459 .append_chunk(buffer)
460 .inspect_err(|_err| {
461 app_data.lost_messages += 1;
462 })
463 })
464 .unwrap_or_else(|err| Err(err.into()))
465 },
466 )
467 })
468 .unwrap_or_else(|err| Err(err.into()))
469 });
470
471 match res {
472 Err(err) => self.schedule_callback(
473 up_calls::UPCALL_TRANSMISSION_ERROR,
474 (error_upcalls::ERROR_RX, err as usize, 0),
475 ),
476 Ok((_first_chunk, new_offset)) => self.schedule_callback(
477 up_calls::UPCALL_MESSAGE_RECEIVED,
478 (
479 0,
480 new_offset as usize,
481 match id {
482 can::Id::Standard(u16) => u16 as usize,
483 can::Id::Extended(u32) => u32 as usize,
484 },
485 ),
486 ),
487 }
488 }
489 Err(err) => {
490 let kernel_err: ErrorCode = err.into();
491 self.schedule_callback(
492 up_calls::UPCALL_TRANSMISSION_ERROR,
493 (error_upcalls::ERROR_RX, kernel_err.into(), 0),
494 )
495 }
496 }
497 }
498
499 fn stopped(&self, buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE]) {
500 self.can_rx.replace(buffer);
501 self.schedule_callback(up_calls::UPCALL_RECEIVED_STOPPED, (0, 0, 0));
502 }
503}