libnfc 1.3.9
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library 00003 * 00004 * Copyright (C) 2009, Roel Verdult 00005 * Copyright (C) 2010, Romain Tartière, Romuald Conty 00006 * 00007 * This program is free software: you can redistribute it and/or modify it 00008 * under the terms of the GNU Lesser General Public License as published by the 00009 * Free Software Foundation, either version 3 of the License, or (at your 00010 * option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, but WITHOUT 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00015 * more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/> 00019 */ 00020 00026 #ifdef HAVE_CONFIG_H 00027 # include "config.h" 00028 #endif // HAVE_CONFIG_H 00029 00030 /* 00031 Thanks to d18c7db and Okko for example code 00032 */ 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <usb.h> 00037 #include <string.h> 00038 00039 #include "../drivers.h" 00040 #include "../chips/pn53x.h" 00041 00042 #include <nfc/nfc.h> 00043 #include <nfc/nfc-messages.h> 00044 00045 #define BUFFER_LENGTH 256 00046 #define USB_TIMEOUT 30000 00047 00048 // Find transfer endpoints for bulk transfers 00049 void 00050 get_end_points (struct usb_device *dev, usb_spec_t * pus) 00051 { 00052 uint32_t uiIndex; 00053 uint32_t uiEndPoint; 00054 struct usb_interface_descriptor *puid = dev->config->interface->altsetting; 00055 00056 // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out 00057 for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) { 00058 // Only accept bulk transfer endpoints (ignore interrupt endpoints) 00059 if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) 00060 continue; 00061 00062 // Copy the endpoint to a local var, makes it more readable code 00063 uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress; 00064 00065 // Test if we dealing with a bulk IN endpoint 00066 if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) { 00067 pus->uiEndPointIn = uiEndPoint; 00068 } 00069 // Test if we dealing with a bulk OUT endpoint 00070 if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) { 00071 pus->uiEndPointOut = uiEndPoint; 00072 } 00073 } 00074 } 00075 00076 bool 00077 pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound, 00078 usb_candidate_t candidates[], int num_candidates, char *target_name) 00079 { 00080 int ret, 00081 i; 00082 00083 struct usb_bus *bus; 00084 struct usb_device *dev; 00085 usb_dev_handle *udev; 00086 uint32_t uiBusIndex = 0; 00087 char string[256]; 00088 00089 string[0] = '\0'; 00090 usb_init (); 00091 00092 // usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed). 00093 if ((ret = usb_find_busses () < 0)) 00094 return false; 00095 // usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed). 00096 if ((ret = usb_find_devices () < 0)) 00097 return false; 00098 00099 *pszDeviceFound = 0; 00100 00101 for (bus = usb_get_busses (); bus; bus = bus->next) { 00102 for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) { 00103 for (i = 0; i < num_candidates; ++i) { 00104 // DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct); 00105 if (candidates[i].idVendor == dev->descriptor.idVendor && candidates[i].idProduct == dev->descriptor.idProduct) { 00106 // Make sure there are 2 endpoints available 00107 // with libusb-win32 we got some null pointers so be robust before looking at endpoints: 00108 if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { 00109 // Nope, we maybe want the next one, let's try to find another 00110 continue; 00111 } 00112 if (dev->config->interface->altsetting->bNumEndpoints < 2) { 00113 // Nope, we maybe want the next one, let's try to find another 00114 continue; 00115 } 00116 if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) { 00117 udev = usb_open (dev); 00118 if (udev) { 00119 usb_get_string_simple (udev, dev->descriptor.iManufacturer, string, sizeof (string)); 00120 if (strlen (string) > 0) 00121 strcpy (string + strlen (string), " / "); 00122 usb_get_string_simple (udev, dev->descriptor.iProduct, string + strlen (string), 00123 sizeof (string) - strlen (string)); 00124 } 00125 usb_close (udev); 00126 } 00127 if (strlen (string) == 0) 00128 strcpy (pnddDevices[*pszDeviceFound].acDevice, target_name); 00129 else 00130 strcpy (pnddDevices[*pszDeviceFound].acDevice, string); 00131 pnddDevices[*pszDeviceFound].pcDriver = target_name; 00132 pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex; 00133 (*pszDeviceFound)++; 00134 // Test if we reach the maximum "wanted" devices 00135 if ((*pszDeviceFound) == szDevices) { 00136 return true; 00137 } 00138 } 00139 } 00140 } 00141 } 00142 if (*pszDeviceFound) 00143 return true; 00144 return false; 00145 } 00146 00147 nfc_device_t * 00148 pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip) 00149 { 00150 nfc_device_t *pnd = NULL; 00151 usb_spec_t *pus; 00152 usb_spec_t us; 00153 struct usb_bus *bus; 00154 struct usb_device *dev; 00155 uint32_t uiBusIndex; 00156 00157 us.uiEndPointIn = 0; 00158 us.uiEndPointOut = 0; 00159 us.pudh = NULL; 00160 00161 DBG ("Attempt to connect to %s device", target_name); 00162 usb_init (); 00163 00164 uiBusIndex = pndd->uiBusIndex; 00165 00166 for (bus = usb_get_busses (); bus; bus = bus->next) { 00167 for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) { 00168 // DBG("Checking device %04x:%04x",dev->descriptor.idVendor,dev->descriptor.idProduct); 00169 if (uiBusIndex == 0) { 00170 // Open the USB device 00171 us.pudh = usb_open (dev); 00172 00173 get_end_points (dev, &us); 00174 if (usb_set_configuration (us.pudh, 1) < 0) { 00175 DBG ("%s", "Setting config failed"); 00176 usb_close (us.pudh); 00177 // we failed to use the specified device 00178 return NULL; 00179 } 00180 00181 if (usb_claim_interface (us.pudh, 0) < 0) { 00182 DBG ("%s", "Can't claim interface"); 00183 usb_close (us.pudh); 00184 // we failed to use the specified device 00185 return NULL; 00186 } 00187 // Allocate memory for the device info and specification, fill it and return the info 00188 pus = malloc (sizeof (usb_spec_t)); 00189 *pus = us; 00190 pnd = malloc (sizeof (nfc_device_t)); 00191 strcpy (pnd->acName, target_name); 00192 pnd->nc = target_chip; 00193 pnd->nds = (nfc_device_spec_t) pus; 00194 pnd->bActive = true; 00195 pnd->bCrc = true; 00196 pnd->bPar = true; 00197 pnd->ui8TxBits = 0; 00198 return pnd; 00199 } 00200 } 00201 } 00202 // We ran out of devices before the index required 00203 DBG ("%s", "Device index not found!"); 00204 return NULL; 00205 } 00206 00207 void 00208 pn53x_usb_disconnect (nfc_device_t * pnd) 00209 { 00210 usb_spec_t *pus = (usb_spec_t *) pnd->nds; 00211 int ret; 00212 00213 if ((ret = usb_release_interface (pus->pudh, 0)) < 0) { 00214 ERR ("usb_release_interface failed (%i)", ret); 00215 } 00216 00217 if ((ret = usb_close (pus->pudh)) < 0) { 00218 ERR ("usb_close failed (%i)", ret); 00219 } 00220 /* 00221 if((ret = usb_reset(pus->pudh)) < 0) { 00222 ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret)); 00223 } 00224 */ 00225 free (pnd->nds); 00226 free (pnd); 00227 } 00228 00229 bool 00230 pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxLen, byte_t * pbtRx, size_t * pszRxLen) 00231 { 00232 size_t uiPos = 0; 00233 int ret = 0; 00234 byte_t abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" 00235 byte_t abtRx[BUFFER_LENGTH]; 00236 usb_spec_t *pus = (usb_spec_t *) pnd->nds; 00237 // TODO: Move this one level up for libnfc-1.6 00238 uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 }; 00239 00240 // Packet length = data length (len) + checksum (1) + end of stream marker (1) 00241 abtTx[3] = szTxLen; 00242 // Packet length checksum 00243 abtTx[4] = 0x0100 - abtTx[3]; 00244 // Copy the PN53X command into the packet abtTx 00245 memmove (abtTx + 5, pbtTx, szTxLen); 00246 00247 // Calculate data payload checksum 00248 abtTx[szTxLen + 5] = 0; 00249 for (uiPos = 0; uiPos < szTxLen; uiPos++) { 00250 abtTx[szTxLen + 5] -= abtTx[uiPos + 5]; 00251 } 00252 00253 // End of stream marker 00254 abtTx[szTxLen + 6] = 0; 00255 00256 #ifdef DEBUG 00257 PRINT_HEX ("TX", abtTx, szTxLen + 7); 00258 #endif 00259 00260 ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTxLen + 7, USB_TIMEOUT); 00261 if (ret < 0) { 00262 DBG ("usb_bulk_write failed with error %d", ret); 00263 pnd->iLastError = DEIO; 00264 return false; 00265 } 00266 00267 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00268 if (ret < 0) { 00269 DBG ("usb_bulk_read failed with error %d", ret); 00270 pnd->iLastError = DEIO; 00271 return false; 00272 } 00273 #ifdef DEBUG 00274 PRINT_HEX ("RX", abtRx, ret); 00275 #endif 00276 00277 if (!pn53x_transceive_check_ack_frame_callback (pnd, abtRx, ret)) 00278 return false; 00279 00280 ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT); 00281 if (ret < 0) { 00282 DBG ("usb_bulk_read failed with error %d", ret); 00283 pnd->iLastError = DEIO; 00284 return false; 00285 } 00286 #ifdef DEBUG 00287 PRINT_HEX ("RX", abtRx, ret); 00288 #endif 00289 00290 #ifdef DEBUG 00291 PRINT_HEX ("TX", ack_frame, 6); 00292 #endif 00293 usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT); 00294 00295 if (!pn53x_transceive_check_error_frame_callback (pnd, abtRx, ret)) 00296 return false; 00297 00298 // When the answer should be ignored, just return a succesful result 00299 if (pbtRx == NULL || pszRxLen == NULL) 00300 return true; 00301 00302 // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) 00303 if (ret < 9) { 00304 DBG ("%s", "No data"); 00305 pnd->iLastError = DEINVAL; 00306 return false; 00307 } 00308 // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable) 00309 *pszRxLen = ret - 7 - 2; 00310 00311 // Get register: nuke extra byte (awful hack) 00312 if ((abtRx[5] == 0xd5) && (abtRx[6] == 0x07) && (*pszRxLen == 2)) { 00313 // DBG("awful hack: abtRx[7]=%02x, abtRx[8]=%02x, we only keep abtRx[8]=%02x", abtRx[7], abtRx[8], abtRx[8]); 00314 *pszRxLen = (*pszRxLen) - 1; 00315 memcpy (pbtRx, abtRx + 8, *pszRxLen); 00316 return true; 00317 } 00318 00319 memcpy (pbtRx, abtRx + 7, *pszRxLen); 00320 00321 return true; 00322 }