/// <summary> /// Removes the reservation for a pin. /// See <see cref="ReservePin"/> for details. /// </summary> /// <param name="pinNumber">The pin number to free, in the numbering scheme of the board</param> /// <param name="usage">The current pin usage</param> /// <param name="owner">The current pin owner</param> /// <exception cref="InvalidOperationException">The pin is not reserved, or the owner is not correct</exception> public virtual void ReleasePin(int pinNumber, PinUsage usage, object owner) { if (!_initialized) { throw new InvalidOperationException("Cannot release a pin if board is not initialized."); } lock (_pinReservationsLock) { if (_pinReservations.TryGetValue(pinNumber, out List <PinReservation>?reservations)) { if (!UsageCanSharePins(usage)) { PinReservation reservation = reservations.Single(); if (reservation.Owner != owner || reservation.Usage != usage) { throw new InvalidOperationException($"Cannot release Pin {pinNumber}, because you are not the owner or the usage is wrong. Class {reservation.Owner} has reserved the Pin for {reservation.Usage}"); } _pinReservations.Remove(pinNumber); } else { PinReservation?reservation = reservations.FirstOrDefault(x => x.Owner == owner); if (reservation == null) { throw new InvalidOperationException($"Cannot release Pin {pinNumber}, because you are not a valid owner."); } if (reservation.Usage != usage) { throw new InvalidOperationException($"Cannot release Pin {pinNumber}, because you are not the owner or the usage is wrong. Class {reservation.Owner} has reserved the Pin for {reservation.Usage}"); } reservations.Remove(reservation); if (reservations.Count == 0) { _pinReservations.Remove(pinNumber); } } } else { throw new InvalidOperationException($"Cannot release Pin {pinNumber}, because it is not reserved."); } } }
/// <summary> /// Reserves a pin for a specific usage. This is done automatically if a known interface (i.e. GpioController) is /// used to open the pin, but may be used to block a pin explicitly, i.e. for UART. /// </summary> /// <param name="pinNumber">The pin number, in the boards default numbering scheme</param> /// <param name="usage">Intended usage of the pin</param> /// <param name="owner">Class that owns the pin (use "this")</param> /// <exception cref="InvalidOperationException">The pin is already reserved</exception> public virtual void ReservePin(int pinNumber, PinUsage usage, object owner) { if (!_initialized) { Initialize(); } lock (_pinReservationsLock) { if (!UsageCanSharePins(usage)) { if (_pinReservations.TryGetValue(pinNumber, out List <PinReservation>?reservations)) { PinReservation reservation = reservations.First(); throw new InvalidOperationException($"Pin {pinNumber} has already been reserved for {reservation.Usage} by class {reservation.Owner}."); } PinReservation rsv = new PinReservation(pinNumber, usage, owner); _pinReservations.Add(pinNumber, new List <PinReservation>() { rsv }); } else { if (_pinReservations.TryGetValue(pinNumber, out List <PinReservation>?reservations)) { PinReservation reservation = reservations.First(); if (reservation.Usage != usage) { throw new InvalidOperationException($"Pin {pinNumber} has already been reserved for {reservation.Usage} by class {reservation.Owner}."); } } else { reservations = new List <PinReservation>(); _pinReservations.Add(pinNumber, reservations); } PinReservation rsv = new PinReservation(pinNumber, usage, owner); reservations.Add(rsv); } } ActivatePinMode(pinNumber, usage); }
internal PinConflictException(Socket socket, Socket.Pin pin, Module module, PinReservation priorReservation) : base("\nUnable to configure the " + (module != null ? module + " " : "") + "module using socket " + socket + " (pin " + (int)pin + "). " + "There is a conflict with the " + (priorReservation.ReservingModule != null ? priorReservation.ReservingModule + " " : "") + "module using socket " + priorReservation.ReservingSocket + " (pin " + priorReservation.ReservingPin + "). Please try using a different combination of sockets.") { }