aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/cdc_mbim.c
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-10-22 06:56:40 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-23 02:40:11 -0400
commit9f651cace30c42e27e726a92f35e4edc55f1ec08 (patch)
tree36a1b04226c4c8a925d09a91bd35337108744ca4 /drivers/net/usb/cdc_mbim.c
parenta82c7ce5bc5be4d0cf8004d1f2ee362f9748c922 (diff)
net: cdc_mbim: Device Service Stream support
MBIM devices can support up to 256 generic streams called Device Service Streams (DSS). The MBIM spec says The format of the Device Service Stream payload depends on the device service (as identified by the corresponding UUID) that is used when opening the data stream. Example use cases are serial AT command interfaces and NMEA data streams. We cannot make any assumptions about these device services. Adding support for Device Service Stream by extending the MBIM session to VLAN mapping scheme, allocating VLAN IDs 256 to 511 for DSS, using the DSS SessionID as the lower 8bit of the VLAN ID. Using a netdev for DSS keeps the device framing intact and allows userspace to do whatever it want with the streams. For example, exporting an AT command interface using DSS session #0 to a PTY for use with a terminal application like minicom: vconfig add wwan0 256 ip link set dev wwan0 up ip link set dev wwan0.256 up socat INTERFACE:wwan0.256,type=2 PTY:,echo=0,link=/tmp/modem Device configuration must be done using MBIM control commands over the /dev/cdc-wdmx device. The userspace management application should coordinate host VLAN configuration and the device MBIM configuration using the device capabilities to find out if it needs to set up PTY mappings etc. Signed-off-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb/cdc_mbim.c')
-rw-r--r--drivers/net/usb/cdc_mbim.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 45f5f50f8f26..42f51c71ec1f 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -149,12 +149,27 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
149 /* mapping VLANs to MBIM sessions: 149 /* mapping VLANs to MBIM sessions:
150 * no tag => IPS session <0> 150 * no tag => IPS session <0>
151 * 1 - 255 => IPS session <vlanid> 151 * 1 - 255 => IPS session <vlanid>
152 * 256 - 4095 => unsupported, drop 152 * 256 - 511 => DSS session <vlanid - 256>
153 * 512 - 4095 => unsupported, drop
153 */ 154 */
154 vlan_get_tag(skb, &tci); 155 vlan_get_tag(skb, &tci);
155 156
156 switch (tci & 0x0f00) { 157 switch (tci & 0x0f00) {
157 case 0x0000: /* VLAN ID 0 - 255 */ 158 case 0x0000: /* VLAN ID 0 - 255 */
159 /* verify that datagram is IPv4 or IPv6 */
160 skb_reset_mac_header(skb);
161 switch (eth_hdr(skb)->h_proto) {
162 case htons(ETH_P_IP):
163 case htons(ETH_P_IPV6):
164 break;
165 default:
166 goto error;
167 }
168 c = (u8 *)&sign;
169 c[3] = tci;
170 break;
171 case 0x0100: /* VLAN ID 256 - 511 */
172 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
158 c = (u8 *)&sign; 173 c = (u8 *)&sign;
159 c[3] = tci; 174 c[3] = tci;
160 break; 175 break;
@@ -163,16 +178,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
163 "unsupported tci=0x%04x\n", tci); 178 "unsupported tci=0x%04x\n", tci);
164 goto error; 179 goto error;
165 } 180 }
166 181 skb_pull(skb, ETH_HLEN);
167 skb_reset_mac_header(skb);
168 switch (eth_hdr(skb)->h_proto) {
169 case htons(ETH_P_IP):
170 case htons(ETH_P_IPV6):
171 skb_pull(skb, ETH_HLEN);
172 break;
173 default:
174 goto error;
175 }
176 } 182 }
177 183
178 spin_lock_bh(&ctx->mtx); 184 spin_lock_bh(&ctx->mtx);
@@ -189,21 +195,23 @@ error:
189 195
190static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci) 196static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
191{ 197{
192 __be16 proto; 198 __be16 proto = htons(ETH_P_802_3);
193 struct sk_buff *skb = NULL; 199 struct sk_buff *skb = NULL;
194 200
195 if (len < sizeof(struct iphdr)) 201 if (tci < 256) { /* IPS session? */
196 goto err; 202 if (len < sizeof(struct iphdr))
203 goto err;
197 204
198 switch (*buf & 0xf0) { 205 switch (*buf & 0xf0) {
199 case 0x40: 206 case 0x40:
200 proto = htons(ETH_P_IP); 207 proto = htons(ETH_P_IP);
201 break; 208 break;
202 case 0x60: 209 case 0x60:
203 proto = htons(ETH_P_IPV6); 210 proto = htons(ETH_P_IPV6);
204 break; 211 break;
205 default: 212 default:
206 goto err; 213 goto err;
214 }
207 } 215 }
208 216
209 skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN); 217 skb = netdev_alloc_skb_ip_align(dev->net, len + ETH_HLEN);
@@ -259,6 +267,10 @@ next_ndp:
259 c = (u8 *)&ndp16->dwSignature; 267 c = (u8 *)&ndp16->dwSignature;
260 tci = c[3]; 268 tci = c[3];
261 break; 269 break;
270 case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
271 c = (u8 *)&ndp16->dwSignature;
272 tci = c[3] + 256;
273 break;
262 default: 274 default:
263 netif_dbg(dev, rx_err, dev->net, 275 netif_dbg(dev, rx_err, dev->net,
264 "unsupported NDP signature <0x%08x>\n", 276 "unsupported NDP signature <0x%08x>\n",