Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/chr/carl9170fw
[carl9170fw.git] / tools / carlu / src / cmd.c
index a6c9020d3a2b587862e00b6932745e59953b2a73..bb87399bb27d01620a0fb46352dd86d703316e06 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * carl9170user - userspace testing utility for ar9170 devices
+ * carlu - userspace testing utility for ar9170 devices
  *
  * Abstraction Layer for FW/HW command interface
  *
- * Copyright 2009, 2010 Christian Lamparter <chunkeey@googlemail.com>
+ * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@
 #include "debug.h"
 #include "fwcmd.h"
 #include "eeprom.h"
+#include "cmd.h"
 
 int carlu_cmd_echo(struct carlu *ar, const uint32_t message)
 {
@@ -56,17 +57,34 @@ int carlu_cmd_echo(struct carlu *ar, const uint32_t message)
        return ret;
 }
 
+struct carl9170_cmd *carlu_cmd_buf(struct carlu *ar,
+       const enum carl9170_cmd_oids cmd, const unsigned int len)
+{
+       struct carl9170_cmd *tmp;
+
+       if (len % 4 || (sizeof(struct carl9170_cmd_head) + len > 64))
+               return ERR_PTR(-EINVAL);
+
+       tmp = malloc(sizeof(struct carl9170_cmd_head) + len);
+       if (tmp) {
+               tmp->hdr.cmd = cmd;
+               tmp->hdr.len = len;
+       }
+       return tmp;
+}
+
 int carlu_cmd_reboot(struct carlu *ar)
 {
+       struct carl9170_cmd *reboot;
        int err;
 
-       err = carlusb_cmd(ar, CARL9170_CMD_REBOOT,
-                         NULL, 0, NULL, 0);
+       /* sure, we could put the struct on the stack too. */
+       reboot = carlu_cmd_buf(ar, CARL9170_CMD_REBOOT_ASYNC, 0);
+       if (IS_ERR_OR_NULL(reboot))
+               return reboot ? PTR_ERR(reboot) : -ENOMEM;
 
-       if (err == -ETIMEDOUT)
-               return 0;
-
-       return err ? err : -1;
+       err = carlusb_cmd_async(ar, reboot, true);
+       return err;
 }
 
 int carlu_cmd_mem_dump(struct carlu *ar, const uint32_t start,
@@ -98,11 +116,40 @@ int carlu_cmd_mem_dump(struct carlu *ar, const uint32_t start,
        return 0;
 }
 
+int carlu_cmd_mem_watch(struct carlu *ar, const uint32_t mem,
+                       const unsigned int len, void *_buf)
+{
+#define RW     8       /* number of words to read at once */
+#define RB     (sizeof(uint32_t) * RW)
+       uint8_t *buf = _buf;
+       unsigned int i, j, block;
+       int err;
+       __le32 offsets[RW];
+
+       for (i = 0; i < (len + RB - 1) / RB; i++) {
+               block = min_t(unsigned int, (len - RB * i) / sizeof(uint32_t), RW);
+               for (j = 0; j < block; j++)
+                       offsets[j] = cpu_to_le32(mem);
+
+               err = carlusb_cmd(ar, CARL9170_CMD_RREG,
+                                   (void *) &offsets, block * sizeof(uint32_t),
+                                   (void *) buf + RB * i, RB);
+
+               if (err)
+                       return err;
+       }
+
+#undef RW
+#undef RB
+
+       return 0;
+}
+
 int carlu_cmd_write_mem(struct carlu *ar, const uint32_t addr,
                        const uint32_t val)
 {
        int err;
-       __le32 msg, block[2] = { addr, val };
+       __le32 msg, block[2] = { cpu_to_le32(addr), cpu_to_le32(val) };
 
        err = carlusb_cmd(ar, CARL9170_CMD_WREG,
                          (void *) &block, sizeof(block),
@@ -110,6 +157,18 @@ int carlu_cmd_write_mem(struct carlu *ar, const uint32_t addr,
        return err;
 }
 
+int carlu_cmd_read_mem(struct carlu *ar, const uint32_t _addr,
+                      uint32_t *val)
+{
+       int err;
+       __le32 msg, addr = { cpu_to_le32(_addr) };
+       err = carlusb_cmd(ar, CARL9170_CMD_RREG, (void *) &addr, sizeof(addr),
+                         (void *) &msg, sizeof(msg));
+
+       *val = le32_to_cpu(msg);
+       return err;
+}
+
 int carlu_cmd_read_eeprom(struct carlu *ar)
 {