aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2021-10-02 22:16:42 +0200
committerNicolas Schodet2021-10-03 10:17:25 +0200
commit6c0730889b6a0a17139d245ad2d3b093af848d68 (patch)
tree70d5c0e9c42ef20dd6cc6ce258895f46b29bb347
parent0ebf261cb559560f1b7bee1fcd1113f3134c0ac1 (diff)
Update code to work with libusb 1.0
-rw-r--r--README6
-rw-r--r--error.c15
-rw-r--r--error.h15
-rw-r--r--lowlevel.c160
-rw-r--r--lowlevel.h6
-rw-r--r--main_fwexec.c9
-rw-r--r--main_fwflash.c9
-rw-r--r--meson.build7
-rw-r--r--samba.c2
-rw-r--r--samba.h2
10 files changed, 143 insertions, 88 deletions
diff --git a/README b/README
index 0d62889..9e8f9bd 100644
--- a/README
+++ b/README
@@ -18,7 +18,7 @@ intelligent brick at a relatively low level. It currently does:
LibNXT is targetted at the platforms that the official Lego Minstorms
NXT software overlooks. Specifically, it will work on any
-POSIX-compliant operating system where libusb 0.1 is supported.
+POSIX-compliant operating system where libusb 1.0 is supported.
The design of LibNXT is layered, meaning you can plug into it at any
level of complexity or abstraction you desire, from the lowest level
@@ -85,10 +85,10 @@ library.
How?
====
-To compile all of this you'll need a copy of libusb 0.1 on your system,
+To compile all of this you'll need a copy of libusb 1.0 on your system,
as well as the Meson build system.
- - Libusb 0.1: https://libusb.info/
+ - Libusb 1.0: https://libusb.info/
- Meson: https://mesonbuild.com/
When you have all that, build with:
diff --git a/error.c b/error.c
index 509e4d1..c0c828d 100644
--- a/error.c
+++ b/error.c
@@ -19,23 +19,26 @@
* USA
*/
+#include <libusb.h>
+
#include "error.h"
static const char *const err_str[] = {
"Success",
"NXT not found on USB bus",
- "Error trying to configure the NXT USB link",
- "NXT USB interface is already claimed by another program",
- "USB write error",
- "USB read error",
- "SAM-BA protocol error",
"NXT handshake failed",
"File open/handling error",
"Invalid firmware image",
+ "Exhausted virtual memory",
};
const char *
nxt_str_error(nxt_error_t err)
{
- return err_str[err];
+ if (err >= NXT_ERROR_USB_MIN)
+ return libusb_strerror(-(err - NXT_ERROR_USB_MIN));
+ else if (err >= 0 && err < sizeof(err_str) / sizeof(err_str[0]))
+ return err_str[err];
+ else
+ return "Unknown error";
}
diff --git a/error.h b/error.h
index d45b036..6de90d1 100644
--- a/error.h
+++ b/error.h
@@ -22,18 +22,17 @@
#ifndef __ERROR_H__
#define __ERROR_H__
+#define NXT_ERROR_USB(ret) (NXT_ERROR_USB_MIN - (ret))
+
typedef enum
{
NXT_OK = 0,
NXT_NOT_PRESENT = 1,
- NXT_CONFIGURATION_ERROR = 2,
- NXT_IN_USE = 3,
- NXT_USB_WRITE_ERROR = 4,
- NXT_USB_READ_ERROR = 5,
- NXT_SAMBA_PROTOCOL_ERROR = 6,
- NXT_HANDSHAKE_FAILED = 7,
- NXT_FILE_ERROR = 8,
- NXT_INVALID_FIRMWARE = 9,
+ NXT_HANDSHAKE_FAILED = 2,
+ NXT_FILE_ERROR = 3,
+ NXT_INVALID_FIRMWARE = 4,
+ NXT_ERROR_NO_MEM = 5,
+ NXT_ERROR_USB_MIN = 1000,
} nxt_error_t;
const char *nxt_str_error(nxt_error_t err);
diff --git a/lowlevel.c b/lowlevel.c
index c5c407c..6806da8 100644
--- a/lowlevel.c
+++ b/lowlevel.c
@@ -19,13 +19,14 @@
* USA
*/
+#include <assert.h>
#include <errno.h>
+#include <libusb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <usb.h>
#include "lowlevel.h"
@@ -33,98 +34,135 @@ const struct
{
int vendor_id;
int product_id;
+ int interface;
} nxt_usb_ids[N_FIRMWARES] = {
- { 0x03EB, 0x6124 }, /* SAM-BA */
- { 0x0694, 0x0002 }, /* LEGO */
- { 0x0694, 0xFF00 } /* NXTOS */
+ { 0x03EB, 0x6124, 1 }, /* SAM-BA */
+ { 0x0694, 0x0002, 0 }, /* LEGO */
+ { 0x0694, 0xFF00, 0 } /* NXTOS */
};
struct nxt_t
{
- struct usb_device *dev;
- struct usb_dev_handle *hdl;
+ libusb_context *usb;
+ libusb_device *dev;
nxt_firmware firmware;
int interface;
+ libusb_device_handle *hdl;
};
nxt_error_t
nxt_init(nxt_t **nxt)
{
- usb_init();
- *nxt = calloc(1, sizeof(**nxt));
+ int ret;
+ nxt_t *lnxt;
+
+ lnxt = calloc(1, sizeof(*lnxt));
+ if (!lnxt)
+ return NXT_ERROR_NO_MEM;
+
+ ret = libusb_init(&lnxt->usb);
+ if (ret < 0)
+ {
+ free(lnxt);
+ return NXT_ERROR_USB(ret);
+ }
+ *nxt = lnxt;
return NXT_OK;
}
nxt_error_t
nxt_find(nxt_t *nxt)
{
- struct usb_bus *busses, *bus;
-
- usb_find_busses();
- usb_find_devices();
+ libusb_device **list;
- busses = usb_get_busses();
+ assert(!nxt->dev);
- for (bus = busses; bus != NULL; bus = bus->next)
+ ssize_t cnt = libusb_get_device_list(nxt->usb, &list);
+ if (cnt < 0)
{
- struct usb_device *dev;
-
- for (dev = bus->devices; dev != NULL; dev = dev->next)
+ return NXT_ERROR_USB(cnt);
+ }
+ for (ssize_t j = 0; j < cnt; j++)
+ {
+ libusb_device *dev = list[j];
+ struct libusb_device_descriptor desc;
+ int ret = libusb_get_device_descriptor(dev, &desc);
+ if (ret == 0)
{
- int i;
-
- for (i = 0; i < N_FIRMWARES; i++)
- if (dev->descriptor.idVendor == nxt_usb_ids[i].vendor_id &&
- dev->descriptor.idProduct == nxt_usb_ids[i].product_id)
- {
- nxt->dev = dev;
- nxt->firmware = i;
- return NXT_OK;
- }
+ for (int i = 0; i < N_FIRMWARES; i++)
+ {
+ if (desc.idVendor == nxt_usb_ids[i].vendor_id &&
+ desc.idProduct == nxt_usb_ids[i].product_id)
+ {
+ libusb_ref_device(dev);
+ libusb_free_device_list(list, 1);
+ nxt->dev = dev;
+ nxt->firmware = i;
+ nxt->interface = nxt_usb_ids[i].interface;
+ return NXT_OK;
+ }
+ }
}
}
+ libusb_free_device_list(list, 1);
return NXT_NOT_PRESENT;
}
nxt_error_t
-nxt_open(nxt_t *nxt, int interface)
+nxt_open(nxt_t *nxt)
{
int ret;
+ libusb_device_handle *hdl;
- nxt->hdl = usb_open(nxt->dev);
-
- // Try to detach driver, but ignore errors, only implemented on Linux
- usb_detach_kernel_driver_np(nxt->hdl, interface);
+ assert(nxt->dev);
+ assert(!nxt->hdl);
- ret = usb_set_configuration(nxt->hdl, 1);
+ ret = libusb_open(nxt->dev, &hdl);
if (ret < 0)
+ return NXT_ERROR_USB(ret);
+
+ // Try to detach driver, but ignore errors when not implemented, or kernel
+ // driver not attached.
+ ret = libusb_detach_kernel_driver(hdl, nxt->interface);
+ if (ret < 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED &&
+ ret != LIBUSB_ERROR_NOT_FOUND)
{
- usb_close(nxt->hdl);
- return NXT_CONFIGURATION_ERROR;
+ libusb_close(hdl);
+ return NXT_ERROR_USB(ret);
}
- ret = usb_claim_interface(nxt->hdl, interface);
- if (ret < 0)
+ ret = libusb_set_configuration(hdl, 1);
+ if (ret < 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED)
{
- usb_close(nxt->hdl);
- return NXT_IN_USE;
+ libusb_close(hdl);
+ return NXT_ERROR_USB(ret);
}
- nxt->interface = interface;
+ ret = libusb_claim_interface(hdl, nxt->interface);
+ if (ret < 0)
+ {
+ libusb_close(hdl);
+ return NXT_ERROR_USB(ret);
+ }
+ nxt->hdl = hdl;
return NXT_OK;
}
-nxt_error_t
+void
nxt_close(nxt_t *nxt)
{
- usb_release_interface(nxt->hdl, nxt->interface);
- usb_close(nxt->hdl);
+ if (nxt->hdl)
+ {
+ libusb_release_interface(nxt->hdl, nxt->interface);
+ libusb_close(nxt->hdl);
+ }
+ if (nxt->dev)
+ libusb_unref_device(nxt->dev);
+ libusb_exit(nxt->usb);
free(nxt);
-
- return NXT_OK;
}
int
@@ -136,9 +174,19 @@ nxt_is_firmware(nxt_t *nxt, nxt_firmware fw)
nxt_error_t
nxt_send_buf(nxt_t *nxt, char *buf, int len)
{
- int ret = usb_bulk_write(nxt->hdl, 0x1, buf, len, 0);
- if (ret < 0)
- return NXT_USB_WRITE_ERROR;
+ int ret;
+ int transfered;
+
+ do
+ {
+ ret = libusb_bulk_transfer(nxt->hdl, 0x01, (unsigned char *)buf, len,
+ &transfered, 0);
+ if (ret < 0)
+ return NXT_ERROR_USB(ret);
+ buf += transfered;
+ len -= transfered;
+ }
+ while (len);
return NXT_OK;
}
@@ -152,9 +200,19 @@ nxt_send_str(nxt_t *nxt, char *str)
nxt_error_t
nxt_recv_buf(nxt_t *nxt, char *buf, int len)
{
- int ret = usb_bulk_read(nxt->hdl, 0x82, buf, len, 0);
- if (ret < 0)
- return NXT_USB_READ_ERROR;
+ int ret;
+ int transfered;
+
+ do
+ {
+ ret = libusb_bulk_transfer(nxt->hdl, 0x82, (unsigned char *)buf, len,
+ &transfered, 0);
+ if (ret < 0)
+ return NXT_ERROR_USB(ret);
+ buf += transfered;
+ len -= transfered;
+ }
+ while (len);
return NXT_OK;
}
diff --git a/lowlevel.h b/lowlevel.h
index 21a728a..15ddc8c 100644
--- a/lowlevel.h
+++ b/lowlevel.h
@@ -22,8 +22,6 @@
#ifndef __LOWLEVEL_H__
#define __LOWLEVEL_H__
-#include <usb.h>
-
#include "error.h"
struct nxt_t;
@@ -39,8 +37,8 @@ typedef enum
nxt_error_t nxt_init(nxt_t **nxt);
nxt_error_t nxt_find(nxt_t *nxt);
-nxt_error_t nxt_open(nxt_t *nxt, int interface);
-nxt_error_t nxt_close(nxt_t *nxt);
+nxt_error_t nxt_open(nxt_t *nxt);
+void nxt_close(nxt_t *nxt);
int nxt_is_firmware(nxt_t *nxt, nxt_firmware fw);
nxt_error_t nxt_send_buf(nxt_t *nxt, char *buf, int len);
nxt_error_t nxt_send_str(nxt_t *nxt, char *str);
diff --git a/main_fwexec.c b/main_fwexec.c
index 65ecd6f..bf4b197 100644
--- a/main_fwexec.c
+++ b/main_fwexec.c
@@ -114,7 +114,7 @@ main(int argc, char *argv[])
if (err == NXT_NOT_PRESENT)
printf("NXT not found. Is it properly plugged in via USB?\n");
else
- NXT_HANDLE_ERR(0, NULL, "Error while scanning for NXT");
+ NXT_HANDLE_ERR(err, nxt, "Error while scanning for NXT");
exit(1);
}
@@ -125,9 +125,8 @@ main(int argc, char *argv[])
exit(2);
}
- NXT_HANDLE_ERR(nxt_open(nxt, NXT_SAMBA_INTERFACE), NULL,
- "Error while connecting to NXT");
- NXT_HANDLE_ERR(nxt_handshake(nxt), NULL, "Error during initial handshake");
+ NXT_HANDLE_ERR(nxt_open(nxt), nxt, "Error while connecting to NXT");
+ NXT_HANDLE_ERR(nxt_handshake(nxt), nxt, "Error during initial handshake");
printf("NXT device in reset mode located and opened.\n"
"Uploading firmware...\n");
@@ -139,7 +138,7 @@ main(int argc, char *argv[])
printf("Firmware uploaded, executing...\n");
NXT_HANDLE_ERR(nxt_jump(nxt, jump_addr), nxt, "Error jumping to C program");
- NXT_HANDLE_ERR(nxt_close(nxt), NULL, "Error while closing connection to NXT");
+ nxt_close(nxt);
printf("Firmware started.\n");
diff --git a/main_fwflash.c b/main_fwflash.c
index 55d7418..d6419af 100644
--- a/main_fwflash.c
+++ b/main_fwflash.c
@@ -75,7 +75,7 @@ main(int argc, char *argv[])
if (err == NXT_NOT_PRESENT)
printf("NXT not found. Is it properly plugged in via USB?\n");
else
- NXT_HANDLE_ERR(0, NULL, "Error while scanning for NXT");
+ NXT_HANDLE_ERR(err, nxt, "Error while scanning for NXT");
exit(1);
}
@@ -86,9 +86,8 @@ main(int argc, char *argv[])
exit(2);
}
- NXT_HANDLE_ERR(nxt_open(nxt, NXT_SAMBA_INTERFACE), NULL,
- "Error while connecting to NXT");
- NXT_HANDLE_ERR(nxt_handshake(nxt), NULL, "Error during initial handshake");
+ NXT_HANDLE_ERR(nxt_open(nxt), nxt, "Error while connecting to NXT");
+ NXT_HANDLE_ERR(nxt_handshake(nxt), nxt, "Error during initial handshake");
printf("NXT device in reset mode located and opened.\n"
"Starting firmware flash procedure now...\n");
@@ -99,6 +98,6 @@ main(int argc, char *argv[])
NXT_HANDLE_ERR(nxt_jump(nxt, 0x00100000), nxt, "Error booting new firmware");
printf("New firmware started!\n");
- NXT_HANDLE_ERR(nxt_close(nxt), NULL, "Error while closing connection to NXT");
+ nxt_close(nxt);
return 0;
}
diff --git a/meson.build b/meson.build
index ce4f339..2687812 100644
--- a/meson.build
+++ b/meson.build
@@ -1,7 +1,7 @@
project('libnxt', 'c',
version : '0.3')
-usbdep = dependency('libusb', version : ['>=0.1', '<1.0'])
+usbdep = dependency('libusb-1.0')
subdir('flash_write')
@@ -20,15 +20,16 @@ lib = static_library('libnxt',
'lowlevel.c',
'samba.c',
flash_routine_h,
+ dependencies : usbdep,
)
executable('fwflash',
'main_fwflash.c',
- link_with : lib, dependencies : usbdep,
+ link_with : lib,
install : true,
)
executable('fwexec',
'main_fwexec.c',
- link_with : lib, dependencies : usbdep,
+ link_with : lib,
install : true,
)
diff --git a/samba.c b/samba.c
index 8b622d4..7dcfb53 100644
--- a/samba.c
+++ b/samba.c
@@ -22,9 +22,9 @@
#include <stdio.h>
#include <string.h>
-#include "samba.h"
#include "error.h"
#include "lowlevel.h"
+#include "samba.h"
static nxt_error_t
nxt_format_command2(char *buf, char cmd, nxt_addr_t addr, nxt_word_t word)
diff --git a/samba.h b/samba.h
index dbd38af..3efd578 100644
--- a/samba.h
+++ b/samba.h
@@ -27,8 +27,6 @@
#include "error.h"
#include "lowlevel.h"
-#define NXT_SAMBA_INTERFACE 1
-
typedef uint32_t nxt_addr_t;
typedef uint32_t nxt_word_t;
typedef uint16_t nxt_hword_t;