0

Is there a usb signal I can send on TX that will generate a response from the computer on the RX only if the computer is active/not a wall usb power supply? I'm trying to use the Remote library when a button is pressed and sometimes it won't work because the computer is off/asleep/etc and in those instances I would like the arduino to behave differently but because I have no way of knowing if the USB power is coming from the wall or passively from a computer that's off or actively from a computer that's on, I can't know what behavior to take.

To be clear about the application in mind: Right now I have a device that sends keyboard signals to my computer using a modified version of Stefan Jones' modified USBAPI.h and HID.cpp files. It works fine but if you restart the computer you have to manually unplug and replug in the arduino to get it to work again. This is necessary every restart, is rather annoying, and adds unnecessary wear to the connector. This is also necessary if the arduino is connected before the OS has loaded. Additionally there are some LEDs on the device (not talking about the diagnostic lights on the arduino itself) that stay lit up at night even when the computer is off. If I could detect when the computer is off/unconnected it would be trivial to fix this.

closed as unclear what you're asking by Chris Stratton, Nick Gammon Aug 1 '16 at 11:02

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • All but two of your tags do not belong, but apart from the obviously inapplicable "signal processing" only you know which. Delete the ones that don't belong. – Chris Stratton Jul 22 '16 at 21:56
  • The atmega32u4 is the chip the arduino micro uses and I mistakenly thought that was also what the uno uses. Signal processing was included because I expect the solution involves measuring the raw signal from the computer but until that is confirmed I'm happy to leave it off. – amoose136 Jul 25 '16 at 3:25
  • That is not what "signal processing" means. – Chris Stratton Jul 25 '16 at 3:30
  • Is "signal processing" not taking analog signals or digital voltages, cleaning them up, and extracting meaning from them? A solution need not use the communication standard to achieve the goal in this case. – amoose136 Jul 25 '16 at 14:57
  • None of which you would be doing in this case, as you are not implementing a USB transceiver yourself, but merely using someone's working chip, USB stack, and apparently protocol driver. And even if you were implementing it yourself (think V-USB), it is arguably too trivial a case to qualify. Go try to find signals or patterns in noise you have to reject and we can start applying the term. – Chris Stratton Jul 25 '16 at 15:10
2

If an MCU which has a built in USB interface (such as the ATmega32u4 on a Leondardo) is properly configured and connected to an operating USB host, it will receive a "Start of Frame" packet every millisecond. I'm not very familiar with the details of the USB engine on that particular chip, but generally you can detect this as an interrupt, or as a change in a peripheral status register bit.

Going a step further, in the Arduino API an if (Serial) test will determine if the board is connected to a host which is in an active CDC-ACM "serial" session with it, ie, one that has a serial terminal or other program talking to it. Again, this only applies to those that implement USB within the chip on which the sketch is running.

Chances are your problems can be fixed by enabling the AVR watchdog timer at one of its longer limits and resetting it in the USB ISR found in USBCore.cpp Then if the the USB goes down (ie, the usual every millisecond SoF interrupt fails to happen for several seconds) your Arduino will reset. In the simple case, it will keep resetting as long as it has power and the USB is down, but you can put some startup logic to wait for the USB while resetting the watchdog if that bothers you. See for comparative example the implementation details behind the if (serial) and create something similar for your chosen USB mode.

  • if (Serial) is not what is needed here I think as that looks for a connection to the arduino serial terminal and the keyboard (which I am using) library does not depend on that. IE, (Serial) may be perpetually false but various Keyboard functions might or might not work. – amoose136 Jul 25 '16 at 15:04
  • I only included the Serial check as an optional more specific extension. The SoF case should catch anything. If you are implementing a keyboard in particular, that protocol may have more specific interaction too, indicating that the host operating system has decided to accept you as a keyboard, and not merely noted your presence on the bus. – Chris Stratton Jul 25 '16 at 15:07
  • Can you provide any further reading references on how to use this possible interrupt? I am not aware of any USB related interrupts in the standard arduino micro development environment. – amoose136 Jul 29 '16 at 21:00
  • You may well need to dig into the source code of what Arduino normally does behind the scenes below the sketch level. You may find they have exposed something for the mode you are using compared to the "if (serial)" that is exposed for the usual USB-serial mode, if not you can fix your issues in the source. Or even more simply, just make sure you don't wait forever for something that may not happen. – Chris Stratton Jul 29 '16 at 22:47
  • I actually have looked at the source code and modified it so the original keyboard library supports proper media keys and such. The problem is rewriting the USB interface is probably 20K LoC in an area I have no expertise in for a problem entirely unrelated to my actual work. My arduino sketch right now is only 175 LoC + ~20 added to the Keyboard/mouse library. – amoose136 Aug 1 '16 at 14:48
0

As I understand, you are trying to implement some peripheral device based on AtMega 8-bit micro-controller that uses USB1.1 interface (FS or LS) to connect to USB host. Your problem seems to be that your host computer (unspecified) puts the port into SUSPEND (sleep), and does not wake up when you try to activate your device (button or something).

First, the USB2.0/1.1 interface does not have any "Tx" or "Rx", it is a half-duplex bi-directional bus. It has D+ and D-, and VBUS. But it is true that a USB peripheral device can generate a bus event called RESUME.

You have two choices. (1) either you make your host computer to never sleep or put USB ports into SUSPEND, or (2) make your device to support RESUME (aka "remote wake-up") function in full compliance with USB specifications.

In case (2) the driver for your device (on host computer) must support remote wake-up function, and this function must be enabled. Then when the host computer is planning to go into one of various sleep modes and decides to SUSPEND your device, it must send special control command to your device which should arm it for wake-up, and the host will be expecting it. In this case the host will never remove VBUS ("passively from computer"), so the device will be able to wake the bus up.

Is this your question about?

  • No, the question is about a device which should behave differently when it is connected to an operating computer vs. a non-operating computer or simple power supply. – Chris Stratton Jul 29 '16 at 4:44
  • Yes what Chris said is true. The solution should be OS agnostic (IE no modifying of drivers on host computer). That said, if I can make the arduino listen for the SUSPEND and RESUME commands the computer might already be sending, I might be able to achieve the goal anyway. – amoose136 Jul 29 '16 at 20:57
  • Then I am confused. On operating computer, your device will connect and will be enumerated and maintain active status as long as host sends SOFs or keep-alives. On non-operating computer the device will not receive any responses from host, and should fall into SUSPEND state (without being armed for remote wake-up). When connected to a charger, this will be similar to non-operaing computer. This behavior is defined in USB2.0 specifications. So what is your question then? – Ale..chenski Jul 29 '16 at 21:13
  • @amoose136: it is not "if you can make the arduino listen to SUSPEND", you must make it so, so your device conforms to USB specification. The SUSPEND function is one of basic USB function. You might elect to do nothing if bus suspend happens, but your interface must wake-up and start responding to host packets if host decides to resume port's activity. – Ale..chenski Jul 29 '16 at 21:28
  • Yes this would probably solve the issue if the device is initially plugged into a computer that is turned on but what if the power goes out? Then no suspend signal is sent and the arduino will try and do the handshake before the OS has had time to boot up so nothing will work. – amoose136 Jul 29 '16 at 21:32
0

Upon having a clarification on what the problem essentially is, the answer is as follows:

(1) There is no way of knowing if the port is a wall charger or inactive computer port, initially. Therefore the initial device behavior must be identical in both cases – asserting pull-up on D+ (assuming it is USB 1.1 FS interface);

(2) However, if the port belongs to a computer, the connect event will awake the host, and the host will issue USB_reset, and perform device enumeration. There is no need to “send any Tx signal” or else, the host will perform this activity by itself. The Arduino software must remember this.

(3) If the host decides to suspend the port (fell asleep), the device must transition into SUSPEND state, and Arduino software must remember this.

(4) If the port was initially in a state with USB totally disabled and does not wake up upon cable attach, see scenario (1);

(5) When/if the host computer is awaken, it will see USB attach status (D+ is up), and will start scenario (2).

In summary, the device (upstream facing port) must implement port functionality in full accord with port state machine described in USB2.0 specifications, Section 9 (Figure 9-1) and Appendix C.2 , Figures C-2 and C-3. As one can see, contrary to the assumption of OP, the port can be in more than two states, and Adruino software must have several different behaviors. Any half-baked implementation of the port state diagram is unacceptable and will cause some functional problem sooner or later.

  • Wow! Downgrade! I guess some people prefer hacking over engineering here. Amazing. – Ale..chenski Jul 30 '16 at 23:06
  • I did not downvote your answer. While I think this is probably the right approach, I'm wondering about the specifics of implementation and why the provided mouse/keyboard library doesn't implement any of this; is there some hardware limitation I don't know about maybe? (arduino.cc/en/Reference/MouseKeyboard) Secondly, given my know how, I don't know if I have the time or experience to implement something so complex. That sounds like several hundred lines of code just for proper USB spec adherence while my actual sketch is probably only 175 LoC in the first place. – amoose136 Aug 1 '16 at 14:41
  • The provided library doesn't implement this because it is not actually necessary for most purposes. What is proposed here is a far, far, far larger task than needed. The is issue is nowhere near as complicated as Ali insists on makes it out to be, but if you want to get distracted into pursuing this, that is your choice. – Chris Stratton Aug 1 '16 at 15:28
  • @Chris: As an engineer with 20+ years in semiconductor industry, yes, I insist that the USB device protocol must be implemented in full accord with specifications, with all states and transitions. The suspend-resume state of USB device are not designated as "optional", their implementation is a "must". If not, the device loses an ability to distinguish an active (but sleepy) host from a dumb charger, or exactly as the OP's situation illustrates. Specifications are written and world-wide adopted for a reason, they represent collective wisdom and experience of many seasoned engineers. – Ale..chenski Aug 1 '16 at 18:47
  • @amoose136: The reference list of Arduino kbd/mouse functions clearly lacking any interface calls to get the USB link status. Apparently the designers of this HID class did not consider the case when USB host might suspend the USB port. As I firmly believe, adherence to USB specifications is your solution. Yes, it is a serious effort. As far as I see, the USB hardware in ATmega32u4 does support "suspend/resume interrupts", so I guess the hardware is USB compliant. – Ale..chenski Aug 1 '16 at 19:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.