summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-01-18 21:31:17 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-01-18 21:31:17 +0000
commitec7a2579b3c778537432615e59b982165728e8ee (patch)
tree9b70ac2eb9a47e5606b4161538369ce8807141e0
parent2d9f09386705e3ca46a181492d20f11cfba8d2af (diff)
Add LED support.
-rw-r--r--sys/dev/usb/if_upgt.c97
-rw-r--r--sys/dev/usb/if_upgtvar.h23
2 files changed, 117 insertions, 3 deletions
diff --git a/sys/dev/usb/if_upgt.c b/sys/dev/usb/if_upgt.c
index 3bac935452d..a4955d40422 100644
--- a/sys/dev/usb/if_upgt.c
+++ b/sys/dev/usb/if_upgt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_upgt.c,v 1.18 2008/01/17 20:46:51 mglocker Exp $ */
+/* $OpenBSD: if_upgt.c,v 1.19 2008/01/18 21:31:16 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -118,6 +118,8 @@ void upgt_rx_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
void upgt_rx(struct upgt_softc *, uint8_t *, int);
int upgt_set_macfilter(struct upgt_softc *, uint8_t state);
int upgt_set_channel(struct upgt_softc *, unsigned);
+void upgt_set_led(struct upgt_softc *, int);
+void upgt_set_led_blink(void *);
int upgt_get_stats(struct upgt_softc *);
int upgt_alloc_tx(struct upgt_softc *);
@@ -246,10 +248,11 @@ upgt_attach(struct device *parent, struct device *self, void *aux)
return;
}
- /* init tasks */
+ /* setup tasks and timeouts */
usb_init_task(&sc->sc_task_newstate, upgt_newstate_task, sc);
usb_init_task(&sc->sc_task_tx, upgt_tx_task, sc);
timeout_set(&sc->scan_to, upgt_next_scan, sc);
+ timeout_set(&sc->led_to, upgt_set_led_blink, sc);
/*
* Open TX and RX USB bulk pipes.
@@ -457,6 +460,7 @@ upgt_detach(struct device *self, int flags)
usb_rem_task(sc->sc_udev, &sc->sc_task_newstate);
usb_rem_task(sc->sc_udev, &sc->sc_task_tx);
timeout_del(&sc->scan_to);
+ timeout_del(&sc->led_to);
/* free xfers */
upgt_free_tx(sc);
@@ -1264,6 +1268,7 @@ upgt_newstate_task(void *arg)
/* do not accept any frames if the device is down */
upgt_set_macfilter(sc, IEEE80211_S_INIT);
+ upgt_set_led(sc, UPGT_LED_OFF);
break;
case IEEE80211_S_SCAN:
DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n",
@@ -1291,6 +1296,7 @@ upgt_newstate_task(void *arg)
ni = ic->ic_bss;
upgt_set_macfilter(sc, IEEE80211_S_RUN);
+ upgt_set_led(sc, UPGT_LED_ON);
break;
}
@@ -1422,6 +1428,8 @@ upgt_tx_task(void *arg)
s = splusb();
+ upgt_set_led(sc, UPGT_LED_BLINK);
+
for (i = 0; i < UPGT_TX_COUNT; i++) {
struct upgt_data *data_tx = &sc->tx_data[i];
@@ -1872,6 +1880,91 @@ upgt_set_channel(struct upgt_softc *sc, unsigned channel)
return (0);
}
+void
+upgt_set_led(struct upgt_softc *sc, int action)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct upgt_data *data_cmd = &sc->cmd_data;
+ struct upgt_lmac_mem *mem;
+ struct upgt_lmac_led *led;
+ struct timeval t;
+ int len;
+
+ /*
+ * Transmit the URB containing the CMD data.
+ */
+ bzero(data_cmd->buf, MCLBYTES);
+
+ mem = (struct upgt_lmac_mem *)data_cmd->buf;
+ mem->addr = htole32(sc->sc_memaddr_frame_start +
+ UPGT_MEMSIZE_FRAME_HEAD);
+
+ led = (struct upgt_lmac_led *)(mem + 1);
+
+ led->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK;
+ led->header1.type = UPGT_H1_TYPE_CTRL;
+ led->header1.len = htole16(
+ sizeof(struct upgt_lmac_led) -
+ sizeof(struct upgt_lmac_header));
+
+ led->header2.reqid = htole32(sc->sc_memaddr_frame_start);
+ led->header2.type = htole16(UPGT_H2_TYPE_LED);
+ led->header2.flags = 0;
+
+ switch (action) {
+ case UPGT_LED_OFF:
+ led->mode = htole16(UPGT_LED_MODE_SET);
+ led->action_fix = 0;
+ led->action_tmp = htole16(UPGT_LED_ACTION_OFF);
+ led->action_tmp_dur = 0;
+ break;
+ case UPGT_LED_ON:
+ led->mode = htole16(UPGT_LED_MODE_SET);
+ led->action_fix = 0;
+ led->action_tmp = htole16(UPGT_LED_ACTION_ON);
+ led->action_tmp_dur = 0;
+ break;
+ case UPGT_LED_BLINK:
+ if (ic->ic_state != IEEE80211_S_RUN)
+ return;
+ if (sc->sc_led_blink)
+ /* previous blink was not finished */
+ return;
+ led->mode = htole16(UPGT_LED_MODE_SET);
+ led->action_fix = htole16(UPGT_LED_ACTION_OFF);
+ led->action_tmp = htole16(UPGT_LED_ACTION_ON);
+ led->action_tmp_dur = htole16(UPGT_LED_ACTION_TMP_DUR);
+ /* lock blink */
+ sc->sc_led_blink = 1;
+ t.tv_sec = 0;
+ t.tv_usec = UPGT_LED_ACTION_TMP_DUR * 1000L;
+ timeout_add(&sc->led_to, tvtohz(&t));
+ break;
+ default:
+ return;
+ }
+
+ len = sizeof(*mem) + sizeof(*led);
+
+ mem->chksum = htole32(upgt_chksum((uint32_t *)led,
+ len - sizeof(*mem)));
+
+ if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) {
+ printf("%s: could not transmit led CMD URB!\n",
+ sc->sc_dev.dv_xname);
+ }
+}
+
+void
+upgt_set_led_blink(void *arg)
+{
+ struct upgt_softc *sc = arg;
+
+ /* blink finished, we are ready for a next one */
+ sc->sc_led_blink = 0;
+ timeout_del(&sc->led_to);
+}
+
int
upgt_get_stats(struct upgt_softc *sc)
{
diff --git a/sys/dev/usb/if_upgtvar.h b/sys/dev/usb/if_upgtvar.h
index d99b64b60c5..8dbdade8dd5 100644
--- a/sys/dev/usb/if_upgtvar.h
+++ b/sys/dev/usb/if_upgtvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_upgtvar.h,v 1.8 2008/01/17 20:46:51 mglocker Exp $ */
+/* $OpenBSD: if_upgtvar.h,v 1.9 2008/01/18 21:31:16 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -70,6 +70,11 @@ struct upgt_tx_radiotap_header {
/* device flags */
#define UPGT_DEVICE_ATTACHED (1 << 0)
+/* leds */
+#define UPGT_LED_OFF 0
+#define UPGT_LED_ON 1
+#define UPGT_LED_BLINK 2
+
/*
* USB xfers.
*/
@@ -219,6 +224,7 @@ struct upgt_lmac_h1 {
#define UPGT_H2_TYPE_TX_DONE 0x0008
#define UPGT_H2_TYPE_STATS 0x000a
#define UPGT_H2_TYPE_EEPROM 0x000c
+#define UPGT_H2_TYPE_LED 0x000d
#define UPGT_H2_FLAGS_TX_ACK_NO 0x0101
#define UPGT_H2_FLAGS_TX_ACK_YES 0x0707
struct upgt_lmac_h2 {
@@ -304,6 +310,19 @@ struct upgt_lmac_channel {
uint32_t pad2;
} __packed;
+#define UPGT_LED_MODE_SET 0x0003
+#define UPGT_LED_ACTION_OFF 0x0002
+#define UPGT_LED_ACTION_ON 0x0003
+#define UPGT_LED_ACTION_TMP_DUR 100 /* ms */
+struct upgt_lmac_led {
+ struct upgt_lmac_h1 header1;
+ struct upgt_lmac_h2 header2;
+ uint16_t mode;
+ uint16_t action_fix;
+ uint16_t action_tmp;
+ uint16_t action_tmp_dur;
+} __packed;
+
struct upgt_lmac_stats {
struct upgt_lmac_h1 header1;
struct upgt_lmac_h2 header2;
@@ -400,6 +419,8 @@ struct upgt_softc {
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
struct timeout scan_to;
+ struct timeout led_to;
+ int sc_led_blink;
unsigned sc_curchan;
int sc_flags;