/* MMMUX - a device access multiplexing library * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Copyright (C) 2012 Soeren Heisrath (forename at surename dot org) */ #include "muxd_hw_rfm12usb.h" #if MMMUX_USE_RFM12USB == 1 /* match usb pid/vid numbers */ int rfm12usb_match_usbid (int in_vid, int in_pid) { /* old usb id (same as usbasp!) - will be removed */ if (in_vid == 0x16C0 && in_pid == 0x05DC) return 1; /* officially assigned VID/PID pair for rfm12usb */ if (in_vid == 0x20a0 && in_pid == 0x4198) return 1; return 0; } /* close the usb connection, remove the hardware from the list */ void rfm12usb_close (void *in_ctx) { rfm12usb_t *rs = ((mmmux_hw_t*) in_ctx)->udata; usb_close (rs->uhandle); rs->uhandle = NULL; mmmux_hw_remove ((mmmux_hw_t*) in_ctx); } ssize_t rfm12usb_tx (void *in_ctx, size_t in_len, void* in_data) { size_t txlen = in_len; int rv; rfm12usb_t *rs = ((mmmux_hw_t*) in_ctx)->udata; switch (rs->mode) { case mode_normal: if (txlen > rs->txlen) txlen = rs->txlen; dbg ("sending %i bytes in NORMAL mode", txlen); rv = usb_control_msg (rs->uhandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, RFMUSB_RQ_RADIO_PUT, 1, 0, (char *) in_data, txlen, DEFAULT_USB_TIMEOUT); break; case mode_ook: if (txlen < sizeof(rfmusb_ook_t)) return 0; dbg ("sending %i bytes in OOK mode: %02X %02X %02X %02X %02X %02X %02X %02X ...", txlen, ((uint8_t *) in_data)[0], ((uint8_t *) in_data)[1], ((uint8_t *) in_data)[2], ((uint8_t *) in_data)[3], ((uint8_t *) in_data)[4], ((uint8_t *) in_data)[5], ((uint8_t *) in_data)[6], ((uint8_t *) in_data)[7] ); rv = usb_control_msg (rs->uhandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, RFMUSB_RQ_OOK_SEND, 1, 0, (char *) in_data, txlen, DEFAULT_USB_TIMEOUT); break; default: return 0; } if (rv > 0) ((mmmux_hw_t*) in_ctx)->txcount += rv; return (ssize_t) rv; } ssize_t rfm12usb_rx (void *in_ctx, size_t in_maxlen, void* out_data) { rfm12usb_t *rs = ((mmmux_hw_t*) in_ctx)->udata; int rv; memset (out_data, 0x00, in_maxlen); rv = usb_control_msg (rs->uhandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, RFMUSB_RQ_RADIO_GET, 0, 0, (char *) out_data, in_maxlen, 100); if (rv > 0) { ((mmmux_hw_t*) in_ctx)->rxcount += rv; return (ssize_t) rv; } return 0; } ssize_t rfm12usb_ctrl (void* in_ctx, mmmux_ctrl_t in_c, void* in_data) { rfm12usb_t *rs = ((mmmux_hw_t*) in_ctx)->udata; dbg ("received CTRL code: %llu", in_c); switch (in_c) { case mode_ook: case mode_normal: rs->mode = in_c; break; default: return 1; } return 0; } /* walk along the usb busses and devices, search for rfm12usb devices * and add them to the hardware list. */ int rfm12usb_find (mmmux_sctx_t *in_c) { struct usb_bus *bus; struct usb_device *dev; uint_fast8_t c = 0; usb_dev_handle *h = NULL; mmmux_hw_t *hws; rfm12usb_t *rs; usb_init(); usb_find_busses(); usb_find_devices(); bus = usb_get_busses(); dbg ("..."); while (bus != NULL) { for (dev = bus->devices; dev != NULL; dev = dev->next) { h = usb_open (dev); if (h == NULL) continue; if (!rfm12usb_match_usbid (dev->descriptor.idVendor, dev->descriptor.idProduct)) continue; dbg ("found rfm12usb device: vid %04X, pid %04X", dev->descriptor.idVendor, dev->descriptor.idProduct); hws = malloc (sizeof(mmmux_hw_t)); memset (hws, 0x00, sizeof(mmmux_hw_t)); /* store rfm12usb specific data in the udata area */ hws->udata = malloc (sizeof(rfm12usb_t)); rs = (rfm12usb_t *) hws->udata; rs->vid = dev->descriptor.idVendor; rs->pid = dev->descriptor.idProduct; rs->txlen = 64; /* XXX hardcoded values for now */ rs->rxlen = 64; rs->uhandle = h; rs->mode = mode_normal; sprintf (hws->name, "RFM12USB device #%u", c++); hws->init = NULL; hws->close = rfm12usb_close; hws->tx = rfm12usb_tx; hws->rx = rfm12usb_rx; hws->ctrl = rfm12usb_ctrl; hws->sdelay = 5000; /* 10ms */ mmmux_hw_add (in_c, hws); } bus = bus->next; } return 0; } #endif