diff -u libnxt.orig/main_jlibnxt.c libnxt/main_jlibnxt.c --- libnxt.orig/main_jlibnxt.c 2010-01-19 09:37:34.428823000 +0100 +++ libnxt/main_jlibnxt.c 2010-01-19 09:44:57.595762000 +0100 @@ -37,12 +37,11 @@ #endif - enum nxt_usb_ids { - VENDOR_LEGO = 0x0694, - VENDOR_ATMEL = 0x03EB, - PRODUCT_NXT = 0x0002, - PRODUCT_SAMBA = 0x6124 + VENDOR_LEGO = 0x0694, + VENDOR_ATMEL = 0x03EB, + PRODUCT_NXT = 0x0002, + PRODUCT_SAMBA = 0x6124 }; @@ -51,247 +50,287 @@ /* Create the device address string. We use the same format as the * Lego Fantom device driver. */ -static -void create_address(struct usb_device *dev, char *address) +static void +create_address(struct usb_device *dev, char *address) { - // Do the easy one first. There is only one Samba device - if (dev->descriptor.idVendor == VENDOR_ATMEL && - dev->descriptor.idProduct == PRODUCT_SAMBA) - sprintf(address, "USB0::0x%04X::0x%04X::NI-VISA-0::1::RAW", VENDOR_ATMEL, PRODUCT_SAMBA); - else - { - // Do the more general case. We need to get the serial number into non - // unicode format. - unsigned char sn_unicode[MAX_SERNO]; - unsigned char sn_ascii[MAX_SERNO]; - struct usb_dev_handle *hdl; - hdl = usb_open(dev); - sn_ascii[0] = '\0'; - if (hdl) - { - int i; - int len = usb_get_string(hdl, dev->descriptor.iSerialNumber, 0, (char *)sn_unicode, MAX_SERNO); - usb_close(hdl); - if (len > 2) - // First byte of the desciptor is the length. Second byte is type. - // Both bytes are included in the length. - len = ((int) sn_unicode[0] - 2)/2; - if (len < 0) - len = 0; - for(i = 0; i < len; i++) - sn_ascii[i] = sn_unicode[i*2 + 2]; - sn_ascii[i] = '\0'; + // Do the easy one first. There is only one Samba device + if (dev->descriptor.idVendor == VENDOR_ATMEL && + dev->descriptor.idProduct == PRODUCT_SAMBA) + sprintf(address, "USB0::0x%04X::0x%04X::NI-VISA-0::1::RAW", + VENDOR_ATMEL, PRODUCT_SAMBA); + else { + // Do the more general case. We need to get the serial number into non + // unicode format. + unsigned char sn_unicode[MAX_SERNO]; + unsigned char sn_ascii[MAX_SERNO]; + struct usb_dev_handle *hdl; + hdl = usb_open(dev); + sn_ascii[0] = '\0'; + if (hdl) { + int i; + int len; + len = usb_get_string(hdl, dev->descriptor.iSerialNumber, 0, + (char *)sn_unicode, MAX_SERNO); + usb_close(hdl); + if (len > 2) { + // First byte of the desciptor is the length. Second byte is type. + // Both bytes are included in the length. + len = ((int)sn_unicode[0] - 2) / 2; + } + if (len < 0) + len = 0; + for(i = 0; i < len; i++) + sn_ascii[i] = sn_unicode[i*2 + 2]; + sn_ascii[i] = '\0'; + } + if (sn_ascii[0] != '\0') + sprintf(address, "USB0::0x%04X::0x%04X::%s::RAW", + dev->descriptor.idVendor, dev->descriptor.idProduct, + sn_ascii); + else + sprintf(address, "USB0::0x%04X::0x%04X::000000000000::RAW", + dev->descriptor.idVendor, dev->descriptor.idProduct); } - if (sn_ascii[0] != '\0') - sprintf(address, "USB0::0x%04X::0x%04X::%s::RAW", dev->descriptor.idVendor, dev->descriptor.idProduct, sn_ascii); - else - sprintf(address, "USB0::0x%04X::0x%04X::000000000000::RAW", dev->descriptor.idVendor, dev->descriptor.idProduct); - } } /* Return a handle to the nth NXT device, or null if not found/error * Also return a dvice address string that contains all of the details of * this device. This string can be used later to re-locate the device */ -static long nxt_find_nth(int idx, char *address) +static long +nxt_find_nth(int idx, char *address) { - struct usb_bus *busses, *bus; - address[0] = '\0'; - if (!initialised) - { - usb_init(); - initialised = 1; - } - if (idx == 0) - { - usb_find_busses(); - usb_find_devices(); - } - - int cnt = 0; - busses = usb_get_busses(); - for (bus = busses; bus != NULL; bus = bus->next) - { - struct usb_device *dev; - - for (dev = bus->devices; dev != NULL; dev = dev->next) - { - if ((dev->descriptor.idVendor == VENDOR_LEGO && - dev->descriptor.idProduct == PRODUCT_NXT) || - (dev->descriptor.idVendor == VENDOR_ATMEL && - dev->descriptor.idProduct == PRODUCT_SAMBA)) - { - if (cnt++ < idx) continue; - // Now create the address string we use the same format as the - // Lego Fantom driver - create_address(dev, address); - return (long) dev; + struct usb_bus *busses, *bus; + address[0] = '\0'; + + if (!initialised) { + usb_init(); + initialised = 1; + } + + if (idx == 0) { + usb_find_busses(); + usb_find_devices(); + } + + int cnt = 0; + busses = usb_get_busses(); + for (bus = busses; bus != NULL; bus = bus->next) { + struct usb_device *dev; + + for (dev = bus->devices; dev != NULL; dev = dev->next) { + if ((dev->descriptor.idVendor == VENDOR_LEGO && + dev->descriptor.idProduct == PRODUCT_NXT) || + (dev->descriptor.idVendor == VENDOR_ATMEL && + dev->descriptor.idProduct == PRODUCT_SAMBA)) { + + if (cnt++ < idx) + continue; + + // Now create the address string we use the same format as the + // Lego Fantom driver + create_address(dev, address); + return (long) dev; } } } - return 0; + + return 0; } // Version of open that works with lejos NXJ firmware. -static -long +static long nxt_open(long hdev) { - struct usb_dev_handle *hdl; - struct usb_device *dev = (struct usb_device *)hdev; - int ret; - char buf[64]; - hdl = usb_open((struct usb_device *) hdev); - if (!hdl) return 0; - ret = usb_set_configuration(hdl, 1); - - if (ret < 0) - { - usb_close(hdl); - return 0; + struct usb_dev_handle *hdl; + struct usb_device *dev = (struct usb_device *)hdev; + int ret; + char buf[64]; + + hdl = usb_open((struct usb_device *) hdev); + if (!hdl) + return 0; + + ret = usb_set_configuration(hdl, 1); + if (ret < 0) { + usb_close(hdl); + return 0; } - // If we are in SAMBA mode we need interface 1, otherwise 0 - if (dev->descriptor.idVendor == VENDOR_ATMEL && - dev->descriptor.idProduct == PRODUCT_SAMBA) - { - ret = usb_claim_interface(hdl, 1); - } - else - { - ret = usb_claim_interface(hdl, 0); - } - - if (ret < 0) - { - usb_close(hdl); - return 0; + + // If we are in SAMBA mode we need interface 1, otherwise 0 + if (dev->descriptor.idVendor == VENDOR_ATMEL && + dev->descriptor.idProduct == PRODUCT_SAMBA) + ret = usb_claim_interface(hdl, 1); + else + ret = usb_claim_interface(hdl, 0); + + if (ret < 0) { + usb_close(hdl); + return 0; } - // Discard any data that is left in the buffer - while (usb_bulk_read(hdl, 0x82, buf, sizeof(buf), 1) > 0) - ; - return (long) hdl; + // Discard any data that is left in the buffer + while (usb_bulk_read(hdl, 0x82, buf, sizeof(buf), 1) > 0) + ; + + return (long)hdl; } // Version of close that uses interface 0 -static void nxt_close(long hhdl) +static void +nxt_close(long hhdl) { - char buf[64]; - struct usb_dev_handle *hdl = (struct usb_dev_handle *) hhdl; - // Discard any data that is left in the buffer - while (usb_bulk_read(hdl, 0x82, buf, sizeof(buf), 1) > 0) - ; - // Release interface. This is a little iffy we do not know which interface - // we are actually using. Releasing both seems to work... but... - usb_release_interface(hdl, 0); - usb_release_interface(hdl, 1); - usb_close(hdl); + char buf[64]; + struct usb_dev_handle *hdl = (struct usb_dev_handle *) hhdl; + + // Discard any data that is left in the buffer + while (usb_bulk_read(hdl, 0x82, buf, sizeof(buf), 1) > 0) + ; + + // Release interface. This is a little iffy we do not know which interface + // we are actually using. Releasing both seems to work... but... + usb_release_interface(hdl, 0); + usb_release_interface(hdl, 1); + usb_close(hdl); } // Implement 20sec timeout write, and return amount actually written -static -int +static int nxt_write_buf(long hdl, char *buf, int len) { - int ret = usb_bulk_write((struct usb_dev_handle *)hdl, 0x1, buf, len, 20000); - return ret; + return usb_bulk_write((struct usb_dev_handle *)hdl, 0x1, buf, len, 20000); } // Implement 20 second timeout read, and return amount actually read -static -int +static int nxt_read_buf(long hdl, char *buf, int len) { - int ret = usb_bulk_read((struct usb_dev_handle *)hdl, 0x82, buf, len, 20000); - return ret; + return usb_bulk_read((struct usb_dev_handle *)hdl, 0x82, buf, len, 20000); } static char samba_serial_no[] = {4, 3, '1', 0}; -int nxt_serial_no(long hdev, char *serno, int maxlen) + +static int +nxt_serial_no(long hdev, char *serno, int maxlen) { - struct usb_device *dev = (struct usb_device *)hdev; - struct usb_dev_handle *hdl; - // If the device is in samba mode it will not have a serial number so we - // return "1" to be in line with the Lego Fantom driver. - if (dev->descriptor.idVendor == VENDOR_ATMEL && - dev->descriptor.idProduct == PRODUCT_SAMBA) - { - memcpy(serno, samba_serial_no, sizeof(samba_serial_no)); - return sizeof(samba_serial_no); - } - hdl = usb_open(dev); - if (!hdl) return 0; - int len = usb_get_string(hdl, dev->descriptor.iSerialNumber, 0, serno, maxlen); - usb_close(hdl); - return len; + struct usb_device *dev = (struct usb_device *)hdev; + struct usb_dev_handle *hdl; + + // If the device is in samba mode it will not have a serial number so we + // return "1" to be in line with the Lego Fantom driver. + if (dev->descriptor.idVendor == VENDOR_ATMEL && + dev->descriptor.idProduct == PRODUCT_SAMBA) { + memcpy(serno, samba_serial_no, sizeof(samba_serial_no)); + return sizeof(samba_serial_no); + } + + hdl = usb_open(dev); + if (!hdl) + return 0; + + int len = + usb_get_string(hdl, dev->descriptor.iSerialNumber, 0, serno, maxlen); + usb_close(hdl); + + return len; } +JNIEXPORT jobjectArray JNICALL +Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1find(JNIEnv *env, jobject obj) +{ + jstring names[MAX_DEVS]; + int cnt = 0; + char name[MAX_SERNO]; + int i = 0; + + while (nxt_find_nth(cnt, name) != 0) { + names[cnt++] = (*env)->NewStringUTF(env, name) ; + } + + if (cnt <= 0) + return NULL; -JNIEXPORT jobjectArray JNICALL Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1find - (JNIEnv *env, jobject obj) -{ - jstring names[MAX_DEVS]; - int cnt = 0; - char name[MAX_SERNO]; - int i = 0; - while(nxt_find_nth(cnt, name) != 0) - { - names[cnt++] = (*env)->NewStringUTF(env, name) ; - } - if (cnt <= 0) return NULL; - - // Now copy names in a java array - jclass sclass = (*env)->FindClass(env, "java/lang/String"); - jobjectArray arr = (*env)->NewObjectArray(env, cnt, sclass, NULL); - for(i = 0; i < cnt; i++) - (*env)->SetObjectArrayElement(env, arr, i, names[i]); + // Now copy names in a java array + jclass sclass = (*env)->FindClass(env, "java/lang/String"); + jobjectArray arr = (*env)->NewObjectArray(env, cnt, sclass, NULL); + for (i = 0; i < cnt; i++) + (*env)->SetObjectArrayElement(env, arr, i, names[i]); - return arr; + return arr; } -JNIEXPORT jlong JNICALL Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1open - (JNIEnv *env, jobject obj, jstring jnxt) +JNIEXPORT jlong JNICALL +Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1open( + JNIEnv *env, jobject obj, jstring jnxt) { - const char* nxt = (*env)->GetStringUTFChars(env, jnxt, 0); - long dev; - char name[MAX_SERNO]; - int cnt = 0; - while((dev = nxt_find_nth(cnt, name)) != 0) - { - if (strcmp(name, nxt) == 0) - { - return (jlong) nxt_open( dev ); + const char* nxt = (*env)->GetStringUTFChars(env, jnxt, 0); + long dev; + char name[MAX_SERNO]; + int cnt = 0; + + while ((dev = nxt_find_nth(cnt, name)) != 0) { + if (strcmp(name, nxt) == 0) + return (jlong)nxt_open(dev); + + cnt++; } - cnt++; - } - return (jlong) 0; -} - -JNIEXPORT void JNICALL Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1close(JNIEnv *env, jobject obj, jlong nxt) { - nxt_close( (long) nxt); -} - -JNIEXPORT jint JNICALL Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1send_1data(JNIEnv *env, jobject obj, jlong nxt, jbyteArray data, jint offset, jint len) { - int ret; - char *jb = (char *) (*env)->GetByteArrayElements(env, data, 0); - if (len > MAX_WRITE) len = MAX_WRITE; - ret = nxt_write_buf((long) nxt, jb+offset, len); - (*env)->ReleaseByteArrayElements(env, data, (jbyte *) jb, 0); - // Assume any error is a timeout!!! Need to fix this! - if (ret < 0) ret = 0; - return ret; -} - -JNIEXPORT jint JNICALL Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1read_1data(JNIEnv *env, jobject obj, jlong nxt, jbyteArray jdata, jint offset, jint len) { - int read_len; - char *jb = (char *)(*env)->GetByteArrayElements(env, jdata, 0); - - read_len = nxt_read_buf((long)nxt, jb + offset, len); - (*env)->ReleaseByteArrayElements(env, jdata, (jbyte *)jb, 0); - if (read_len == -ETIMEDOUT) read_len = 0; - return read_len; + + return (jlong)0; +} + +JNIEXPORT void JNICALL +Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1close( + JNIEnv *env, jobject obj, jlong nxt) +{ + nxt_close( (long) nxt); } +JNIEXPORT jint JNICALL +Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1send_1data( + JNIEnv *env, jobject obj, jlong nxt, jbyteArray data, jint offset, + jint len) +{ + int ret; + char *jb; + + if (len > MAX_WRITE) + len = MAX_WRITE; + + jb = (char *) (*env)->GetByteArrayElements(env, data, 0); + ret = nxt_write_buf((long) nxt, jb+offset, len); + (*env)->ReleaseByteArrayElements(env, data, (jbyte *) jb, 0); + + // TODO: Assume any error is a timeout!!! Need to fix this! + if (ret < 0) + ret = 0; + + return ret; +} + +JNIEXPORT jint JNICALL +Java_lejos_pc_comm_NXTCommLibnxt_jlibnxt_1read_1data( + JNIEnv *env, jobject obj, jlong nxt, jbyteArray jdata, jint offset, + jint len) +{ + int read_len; + char *jb; + + jb = (char *)(*env)->GetByteArrayElements(env, jdata, 0); + read_len = nxt_read_buf((long)nxt, jb + offset, len); + (*env)->ReleaseByteArrayElements(env, jdata, (jbyte *)jb, 0); + + if (read_len == -ETIMEDOUT) + read_len = 0; + + return read_len; +} + +/* + * Local Variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */